Line by line file read

Line by line file read

Post by TPG Network R & » Thu, 06 Jun 1996 04:00:00



I need to write a bash script that will do the following:
Read a file line by line each line having the same format:
It has an unknown number of lines with each line having the format:
name1 name2 name3 name4 name5
I want to assign each of the names to a variable and then perform all other
necessary operations with these variables.  I thought the builtin "read" command
would do the job, but it continually reads from the start of the file.  
Can anyone help?

Thanks.

 
 
 

Line by line file read

Post by Icarus Spar » Thu, 06 Jun 1996 04:00:00




Quote:>I need to write a bash script that will do the following: Read a file
>line by line each line having the same format: It has an unknown number
>of lines with each line having the format:
> name1 name2 name3 name4 name5
> I want to assign each of the names to a variable and then perform
>all other necessary operations with these variables. I thought the
>builtin "read" command would do the job, but it continually reads from
>the start of the file. Can anyone help?

The builtin 'read is indeed the correct thing to use. I suspect from
your description that you are saying

while :
do
read name1 name2 name3 name4 name5 < file
...
done

instead of the correct

while read name1 name2 name3 name4 name5
do
...
done < file

 
 
 

Line by line file read

Post by Chet Ram » Thu, 06 Jun 1996 04:00:00




Quote:>I need to write a bash script that will do the following:
>Read a file line by line each line having the same format:
>It has an unknown number of lines with each line having the format:
>name1 name2 name3 name4 name5
>I want to assign each of the names to a variable and then perform all other
>necessary operations with these variables.  I thought the builtin "read" command
>would do the job, but it continually reads from the start of the file.  

while read name1 name2 name3 name4 name5
do
        ...process $name?
done < input-file
--
``The lyf so short, the craft so long to lerne.'' - Chaucer


 
 
 

Line by line file read

Post by R Schram » Tue, 18 Jun 1996 04:00:00


This would be much, much easier in perl, but as this is the shell group,
it can be done, although awkwardly.

First, find out how many lines there are in the file, then loop through
doing a head -num | tail -1.  Then do a cut to get the elements.  example
(I'm not a BASHer, but use sh):

num=0
linenum=`wc -l filename`
while $linenum > $num
do
num=`expr num + 1` # or something like that
line=`head -$num | tail -1`
# read num lines into the file, then just the last line, then increment
the number lines read,
# so that the tail gets the last line each time, or individual lines
$field1=`cut -d:{tab or whatever} -f1`
$field2=`cut -d:{tab or whatever} -f2` #etc.
do what ever to the vars
done

Now in perl, it is easier (this is what the Practical Extraction and
Reporting Language was designed for:

$file="filename";
open(FILE,$file);
while(<FILE>){
($field1, $field2, $field3, etc.) = split(/\+w/); # splits the line on
however much whitespace into fields.
do what ever to the vars;

Quote:}

A little more elegant, and lots faster.

good luck,

Rich


Quote:> I need to write a bash script that will do the following:
> Read a file line by line each line having the same format:
> It has an unknown number of lines with each line having the format:
> name1 name2 name3 name4 name5
> I want to assign each of the names to a variable and then perform all
other
> necessary operations with these variables.  I thought the builtin "read"
command
> would do the job, but it continually reads from the start of the file.  
> Can anyone help?

> Thanks.

 
 
 

Line by line file read

Post by Dave Bro » Wed, 19 Jun 1996 04:00:00



: This would be much, much easier in perl, but as this is the shell group,
: it can be done, although awkwardly.
:
: First, find out how many lines there are in the file, then loop through
: doing a head -num | tail -1.  Then do a cut to get the elements.  example
: (I'm not a BASHer, but use sh):
:
: num=0
: linenum=`wc -l filename`
: while $linenum > $num
: do
: num=`expr num + 1` # or something like that
: line=`head -$num | tail -1`
: # read num lines into the file, then just the last line, then increment
: the number lines read,
: # so that the tail gets the last line each time, or individual lines
: $field1=`cut -d:{tab or whatever} -f1`
: $field2=`cut -d:{tab or whatever} -f2` #etc.
: do what ever to the vars
: done

*y hell, that's an O(n^2) read through the file.  DO NOT DO THIS.
Really.  I had a script written like this one (Hi Jim!), and it took
eight hours, until I fixed it, and then it took less than 30 seconds.

while read line
do
    # do stuff here
done < file

: Now in perl, it is easier (this is what the Practical Extraction and
: Reporting Language was designed for:
:
: $file="filename";
: open(FILE,$file);
: while(<FILE>){
: ($field1, $field2, $field3, etc.) = split(/\+w/); # splits the line on
: however much whitespace into fields.
: do what ever to the vars;
: }

I certainly hope you don't write production code like that, with no
indentation.  If I had to maintain code written like that, I'd just
delete it.

--Dave

 
 
 

Line by line file read

Post by Donn Ca » Wed, 19 Jun 1996 04:00:00



| This would be much, much easier in perl, but as this is the shell group,
| it can be done, although awkwardly.

It certainly can be done awkwardly!  But perhaps it doesn't need
to be quite as awkward as this.  The original article, and I suspect
some reasonable responses, have expired here, so I hope the following
doesn't tediously repeat what has already been said on the matter:

The < redirection operator opens the file or device, which is why you
always start from the first line when you write "read x y z < file".
For a redirection that continues from the last read, you need an already
open file - that is, a UNIX "unit" that stays open between redirections.
This requires three basic Bourne shell features:  unit numbers, stream
duping and the I/O "exec".

Unit numbers are just as per UNIX, except I think the range is 0 to 9.
The number is simply specified in front of the redirection operator.
The ordinary > and < are the same as 1> and 0<, respectively.  The UNIX
dup2(2) system call is accomplished by the >& operator - for example,
1>&2 redirects output to the diagnostic/error stream.  The "exec"
statement, when used with no command, can perform redirections in
the shell process itself.  Hence:

 exec 5< file                                    #open file on unit 5
 while read x y z <&5                       #redirect input to unit 5
 do something with $x $y $z
 done

The choice of "5" is arbitrary.  If you are indeed using a "while"
loop or similar construct, you may find it more convenient to
simply redirect input for the whole block -
 while read x y z; do something; done < file
In such cases, look out for pipelines that may cause the shell
block to be executed in a subshell, with its own variables.

    Donn Cave, University Computing Services, University of Washington

-------- original article --------


| > I need to write a bash script that will do the following:
| > Read a file line by line each line having the same format:
| > It has an unknown number of lines with each line having the format:
| > name1 name2 name3 name4 name5
| > I want to assign each of the names to a variable and then perform all
| other
| > necessary operations with these variables.  I thought the builtin "read"
| command
| > would do the job, but it continually reads from the start of the file.  
| > Can anyone help?
| >
| > Thanks.
| >