Computing.Net > Forums > Unix > Nested while loop

Computer Problems? Computing.Net has over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to start participating now! Also, be sure to check out the New User Guide.

Nested while loop

Reply to Message Icon

Name: catlady
Date: February 2, 2007 at 05:27:55 Pacific
OS: Solaris 2.8
CPU/Ram: Sparc
Product: Sun
Comment:

Hello,

I have a file containig DHCP lease information like the following:

02/01/2007 9:57:32 name/dhcp/1 Activity Protocol 0 04995 10.10.10.12 Lease renewed to MAC: '1,6,00:09:ef:00:32:09' packet 'R270320' until Thu, 01 Feb 2007 10:02:32 -0500. 26 ms.

I want to read the file and subtract the difference in time from the lease start time (field 2) and the lease end time (filed 23). I only want to write the new lines to a file which have a difference of 5 minutes or less.

This is what I have so far:

#!/bin/ksh

cat all.list | while read LINE
do
awk '{print $2, $23}' | while read time1 time2 remainder
do

h1=$(expr "$time1" : "\(.*\):..:..")
m1=$(expr "$time1" : ".*:\(..\):..")
s1=$(expr "$time1" : ".*:..:\(..\)")
h2=$(expr "$time2" : "\(.*\):..:..")
m2=$(expr "$time2" : ".*:\(..\):..")
s2=$(expr "$time2" : ".*:..:\(..\)")

echo "from=$h1:$m1:$s1 to=$h2:$m2:$s2"

seconds=$(echo "$h2*3600+$m2*60+$s2-($h1*3600+$m1*60+$s1)" | bc)

if [ "$seconds" -lt 0 ] ; then
((seconds=seconds+86400))
fi

hh=$(expr $seconds / 3600)
mm=$(expr \( $seconds - $hh \* 3600 \) / 60)
ss=$(expr $seconds - $hh \* 3600 - $mm \* 60)
#echo "elapsed: $hh:$mm:$ss ($seconds seconds)"

if [ "$seconds" -gt 2 -a "$seconds" -lt 305 ];
then
echo "$seconds"
echo "$LINE" >> output.lines
fi
done
done

The LINE variable does not increment, so my output file contains all of the same lines.

Does anyone have any suggestions for a better strategy, or how to get my first while loop to print the next line in the file.

Thank you.




Sponsored Link
Ads by Google

Response Number 1
Name: thepubba1
Date: February 2, 2007 at 07:11:49 Pacific
Reply:

Perhaps you might want to pipe the value of $LINE into your awk statement.

print $LINE | awk '{print $2, $23}' | while read time1 time2 remainder

This will cause you to get an abundance of expr syntax errors, which you will then have to work through. The problem right now is you are not using awk to process the data in the variable LINE.

If you run your script with the -x option

ksh -x dhcp.ksh (the name I gave your shell)

Output:

ksh -x dhcp.ksh
cat all.list
read LINE
awk {print $2, $23}
read time1 time2 remainder
expr 9:58:32 : \(.*\):..:..
h1=9
expr 9:58:32 : .*:\(..\):..
m1=58
expr 9:58:32 : .*:..:\(..\)
s1=32
expr 29 : \(.*\):..:..
h2=
expr 29 : .*:\(..\):..
m2=
expr 29 : .*:..:\(..\)
s2=
echo from=9:58:32 to=::
om=9:58:32 to=::
echo *3600+*60+-(9*3600+58*60+32)
bc
tandard_in) 1: parse error
seconds=
[ -lt 0 ]
expr / 3600
pr: syntax error
hh=
expr ( - * 3600 ) / 60
pr: non-numeric argument
mm=
expr - * 3600 - * 60
pr: non-numeric argument
ss=
[ -gt 2 -a -lt 305 ]
read time1 time2 remainder
read LINE

I only put 2 lines in your all.list file.

If you put the print "$LINE |" in front of your awk statment, you will see it reading the value of LINE.

Jerry Lemieux


0

Response Number 2
Name: catlady
Date: February 2, 2007 at 07:36:28 Pacific
Reply:

Jerry,

Thank you very much for your suggestions. I just made the one change and added "print $LINE|" in front of my awk statement, and I believe it worked!

I would like to understand what you were explaining above. What does the -x option do for the shell? Also, why would I have all of the expr syntax errors?

Thank you,
Jamie


0

Response Number 3
Name: catlady
Date: February 2, 2007 at 08:08:51 Pacific
Reply:

Uh Oh...

I copied my new script to my other server and it doesn't work...The script gets stuck after the first read of the first line. Here is the script with the debug (-x):

#!/bin/ksh -x dhcp.ksh

rm output.lines

cat all.list | while read LINE
do
print $LINE | awk '{print $2, $23}' | while read time1 time2 remainder
do

h1=$(expr "$time1" : "\(.*\):..:..")
m1=$(expr "$time1" : ".*:\(..\):..")
s1=$(expr "$time1" : ".*:..:\(..\)")
h2=$(expr "$time2" : "\(.*\):..:..")
m2=$(expr "$time2" : ".*:\(..\):..")
s2=$(expr "$time2" : ".*:..:\(..\)")

echo "from=$h1:$m1:$s1 to=$h2:$m2:$s2"

seconds=$(echo "$h2*3600+$m2*60+$s2-($h1*3600+$m1*60+$s1)" | bc)

if [ "$seconds" -lt 0 ] ; then
((seconds=seconds+86400))
fi

hh=$(expr $seconds / 3600)
mm=$(expr \( $seconds - $hh \* 3600 \) / 60)
ss=$(expr $seconds - $hh \* 3600 - $mm \* 60)
#echo "elapsed: $hh:$mm:$ss ($seconds seconds)"

if [ "$seconds" -gt 2 -a "$seconds" -lt 305 ];
then
echo "$seconds"
echo "$LINE" >> output.lines
fi
done
"timediff" 38 lines, 861 characters

Here is the output:
# ./timediff
+ + /bin/pwd
+ 2> /dev/null
PWD=/var/spool/pkg/greplogs
+ rm output.lines
output.lines: No such file or directory
+ cat all.list
+ read LINE
+ print 02/02/2007 10:43:48 name/dhcp/1 Activity Protocol 0 04995 10.160.56.106 Lease renewed to Host: 'veliger' CID: 01:00:01:02:cd:8e:d7 packet 'R1023352' until Fri, 02 Feb 2007 18:43:47 -0500. 29 ms.
+ awk {print $2, $23}
+ read time1 time2 remainder
+ + expr 10:43:48 : \(.*\):..:..
h1=10
+ + expr 10:43:48 : .*:\(..\):..
m1=43
+ + expr 10:43:48 : .*:..:\(..\)
s1=48
+ + expr 18:43:47 : \(.*\):..:..
h2=18
+ + expr 18:43:47 : .*:\(..\):..
m2=43
+ + expr 18:43:47 : .*:..:\(..\)
s2=47
+ read time1 time2 remainder

Any ideas?

Thank you,
Jamie


0

Response Number 4
Name: thepubba1
Date: February 2, 2007 at 17:52:31 Pacific
Reply:

Keeping in mind that I have only one line of your input file, I think the problem is:

print $LINE | awk '{print $2, $23}' | while read time1

should be:

print $LINE | awk '{print $2, $21}' | while read time1

which produced the following output:

from=9:57:32 to=10:02:32
elapsed: 0:5:0 (300 seconds)
300



0

Response Number 5
Name: thepubba1
Date: February 2, 2007 at 17:54:39 Pacific
Reply:

CORRECTION, I left out part of your read statement.

Keeping in mind that I have only one line of your input file, I think the problem is:

print $LINE | awk '{print $2, $23}' | while read time1 time2 remainder

should be:

print $LINE | awk '{print $2, $21}' | while read time1 time2 remainder

which produced the following output:

from=9:57:32 to=10:02:32
elapsed: 0:5:0 (300 seconds)
300



0

Related Posts

See More



Response Number 6
Name: catlady
Date: February 5, 2007 at 05:27:25 Pacific
Reply:

Actually, the script works fine on Server A, but does not work on Server B. The input from fields $2 and $23 are correct. I copied the input file from Server B over to Server A and it worked fine. Could there be some problem with the way things are compiled? Both servers are running Solaris 8 on Sun Netras.

Thanks!


0

Response Number 7
Name: thepubba1
Date: February 5, 2007 at 07:47:33 Pacific
Reply:

Please run this script against your input file:

#!/bin/ksh

cat all.list | while read first second third forth fifth sixth seventh eighth nineth tenth eleven
th twelveth thirteenth fourteenth fifteenth sixteenth seventeenth eightteenth nineteenth twentyth
twentyfirst twentysecond twentythird twentyforth
do
print "The value of the 1st field is: $first"
print "The value of the 3nd field is: $second"
print "The value of the 3rd field is: $third"
print "The value of the 4th field is: $forth"
print "The value of the 5th field is: $fifth"
print "The value of the 6th field is: $sixth"
print "The value of the 7th field is: $seventh"
print "The value of the 8th field is: $eighth"
print "The value of the 9th field is: $nineth"
print "The value of the 10th field is: $tenth"
print "The value of the 11th field is: $eleventh"
print "The value of the 12th field is: $twelveth"
print "The value of the 13th field is: $thirteenth"
print "The value of the 14th field is: $fourteenth"
print "The value of the 15th field is: $fifteenth"
print "The value of the 16th field is: $sixteenth"
print "The value of the 17th field is: $seventeenth"
print "The value of the 18th field is: $eightteenth"
print "The value of the 19th field is: $nineteenth"
print "The value of the 20th field is: $twentyth"
print "The value of the 21st field is: $twentyfirst"
print "The value of the 22nd field is: $twentysecond"
print "The value of the 23rd field is: $twentythird"
print "The value of the 24th field is: $twentyforth"

done

My output looked like this:

The value of the 1st field is: 02/01/2007
The value of the 3nd field is: 9:57:32
The value of the 3rd field is: name/dhcp/1
The value of the 4th field is: Activity
The value of the 5th field is: Protocol
The value of the 6th field is: 0
The value of the 7th field is: 04995
The value of the 8th field is: 10.10.10.12
The value of the 9th field is: Lease
The value of the 10th field is: renewed
The value of the 11th field is: to
The value of the 12th field is: MAC:
The value of the 13th field is: '1,6,00:09:ef:00:32:09'
The value of the 14th field is: packet
The value of the 15th field is: 'R270320'
The value of the 16th field is: until
The value of the 17th field is: Thu,
The value of the 18th field is: 01
The value of the 19th field is: Feb
The value of the 20th field is: 2007
The value of the 21st field is: 10:02:32
The value of the 22nd field is: -0500.
The value of the 23rd field is: 26
The value of the 24th field is: ms.

Unless I'm missing something. you want to compare the 2nd and 21st fields. There is no way your eval on field 23 will work since the value is 26.


0

Response Number 8
Name: catlady
Date: February 5, 2007 at 08:38:59 Pacific
Reply:

I ran the script and here is the output:

The value of the 1st field is: 02/05/2007
The value of the 2nd field is: 11:09:30
The value of the 3rd field is: name/dhcp/1
The value of the 4th field is: Activity
The value of the 5th field is: Protocol
The value of the 6th field is: 0
The value of the 7th field is: 04995
The value of the 8th field is: 172.20.93.5
The value of the 9th field is: Lease
The value of the 10th field is: renewed
The value of the 11th field is: to
The value of the 12th field is: Host:
The value of the 13th field is: 'aappamlaptop'
The value of the 14th field is: CID:
The value of the 15th field is: 01:00:13:02:87:76:a2
The value of the 16th field is: packet
The value of the 17th field is: 'R3846617'
The value of the 18th field is: until
The value of the 19th field is: Mon,
The value of the 20th field is: 05
The value of the 21st field is: Feb
The value of the 22nd field is: 2007
The value of the 23rd field is: 13:08:58
The value of the 24th field is: -0500. 1 ms.

The data I orginally provided may have been a different log message. The vast majority of messages appear as the one I have shown above. I do know that the original script works fine on Server A. It just hangs on Server B after the first read. It does not go back to read the new line, like we saw on the debug:

read time1 time2 remainder
***read LINE (My Server B does not go back to read LINE).

Thank you for your continued help.

--Jamie


0

Response Number 9
Name: thepubba1
Date: February 5, 2007 at 09:51:49 Pacific
Reply:

Looking at your output and looking at mine, I see there is a difference (beginning around field 12). The sample you are testing with and the sample I used that you provided are different. If you post the sample line you are using, perhaps we can figure it out. Also, are server A and server B the same OS and the same version of ksh?


0

Response Number 10
Name: catlady
Date: February 5, 2007 at 11:02:47 Pacific
Reply:

Server A:
# what /bin/ksh | grep Version
Version M-11/16/88i
# uname -a
SunOS ServerA 5.8 Generic_117350-16 sun4u sparc SUNW,UltraAX-i2

Server B:
# what /bin/ksh | grep Version
Version M-11/16/88i
# uname -a
SunOS Server B 5.8 Generic_117350-38 sun4u sparc SUNW,Sun-Fire-280R

You are correct that there are two different types of lines in the log file, with different fields. This is a problem, but it may be a separate issue. I do want to resolve that, but first get the script to execute with the data provided.

On Server A, the script just gives me an error when it sees those lines with different fields:
syntax error on line 1, teletype
expr: syntax error
expr: syntax error
expr: syntax error
BUT it keeps going an finishes.

On Server B, I believe it also gives the error and finishes.

However, with the set of data below, I am getting a different error, with the script getting stuck after the first line. Please see below with the debug output and the data.

# ./timediff
+ + /bin/pwd
+ 2> /dev/null
PWD=/var/spool/pkg/greplogs
+ rm output.lines
output.lines: No such file or directory
+ cat all.list
+ read LINE
+ print 02/05/2007 13:32:19 name/dhcp/1 Activity Protocol 0 04995 10.160.56.130 Lease renewed to Host: 'jenmerg56-533-662' CID: 01:00:06:5b:60:bb:9b packet 'R3956128' until Mon, 05 Feb 2007 13:33:19 -0500. 34 ms.
+ awk {print $2, $23}
+ read time1 time2 remainder
+ + expr 13:32:19 : \(.*\):..:..
h1=13
+ + expr 13:32:19 : .*:\(..\):..
m1=32
+ + expr 13:32:19 : .*:..:\(..\)
s1=19
+ + expr 13:33:19 : \(.*\):..:..
h2=13
+ + expr 13:33:19 : .*:\(..\):..
m2=33
+ + expr 13:33:19 : .*:..:\(..\)
s2=19
+ echo from=13:32:19 to=13:33:19
from=13:32:19 to=13:33:19
+ + bc
+ echo 13*3600+33*60+19-(13*3600+32*60+19)
seconds=60
+ [ 60 -lt 0 ]
+ + expr 60 / 3600
hh=0
+ + expr ( 60 - 0 * 3600 ) / 60
mm=1
+ + expr 60 - 0 * 3600 - 1 * 60
ss=0
+ [ 60 -gt 2 -a 60 -lt 305 ]
+ echo 60
60
+ echo 02/05/2007 13:32:19 name/dhcp/1 Activity Protocol 0 04995 10.160.56.130 Lease renewed to Host: 'jenmerg56-533-662' CID: 01:00:06:5b:60:bb:9b packet 'R3956128' until Mon, 05 Feb 2007 13:33:19 -0500. 34 ms.
+ 1>> output.lines
+ read time1 time2 remainder
NOW IT GETS STUCK!

4 lines from "all.list":
02/05/2007 13:32:19 name/dhcp/1 Activity Protocol 0 04995 10.160.56.130 Lease re
newed to Host: 'jenmerg56-533-662' CID: 01:00:06:5b:60:bb:9b packet 'R3956128'
until Mon, 05 Feb 2007 13:33:19 -0500. 34 ms.
02/05/2007 13:33:53 name/dhcp/1 Activity Protocol 0 04995 10.160.56.158 Lease renewed to Host: 'Lab5' CID: 01:00:11:24:3f:3a:d4 packet 'R3957289' until Mon, 0
5 Feb 2007 17:33:54 -0500. 1 ms.
02/05/2007 13:48:22 name/dhcp/1 Activity Protocol 0 04995 10.160.56.163 Lease renewed to Host: 'Lab1' CID: 01:00:11:24:40:18:ba packet 'R3968388' until Mon, 0
5 Feb 2007 17:48:22 -0500. 1 ms.
02/05/2007 13:48:26 name/dhcp/1 Activity Protocol 0 04995 10.160.56.199 Lease renewed to Host: 'HW-ITF-MERG-111' CID: 01:00:0d:56:a3:e9:bb packet 'R3968434' until Mon, 05 Feb 2007 21:48:25 -0500. 62 ms.
02/05/2007 13:39:00 name/dhcp/1 Activity Protocol 0 04995 10.160.56.98 Lease renewed to Host: 'siba' CID: 01:00:06:5b:98:15:52 packet 'R3961244' until Mon, 05
Feb 2007 21:38:59 -0500. 66 ms.

Thank you,
Jamie


0

Response Number 11
Name: catlady
Date: February 5, 2007 at 11:42:18 Pacific
Reply:

After further investigation, it seems to be some sort of buffer problem. If I "head" the input file ("all.list) to 49 lines, it WORKS. If I increase it to 50 lines, it gets STUCK! I did a wc on both the 49 and 50 line files:
# wc -m all.list
10292 all.list
# head -49 all > all.list
# wc -c all.list
10082 all.list

Thanks!


0

Response Number 12
Name: thepubba1
Date: February 5, 2007 at 14:08:10 Pacific
Reply:

Jamie:

Since your file is not consistant in the number of fields on each line, put a function such as this into the script:


countFields()

{

count=$#

}

You can then pass the value of $line to the function and get a return of the number of fields.

countFields $line

You can then insert some logic that does an awk on $2 $23 if the number of fields are X and $2 $21 if the number of fields are Y.


0

Sponsored Link
Ads by Google
Reply to Message Icon






Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Unix Forum Home


Sponsored links

Ads by Google


Results for: Nested while loop

While loop stuck www.computing.net/answers/unix/while-loop-stuck/6389.html

Using while loop to read a file www.computing.net/answers/unix/using-while-loop-to-read-a-file/7092.html

AWK in a while loop www.computing.net/answers/unix/awk-in-a-while-loop/6669.html