Click to See Complete Forum and Search --> : reading lines from a text file (1 at a time) w/Bash
eflashj
04-02-2002, 05:00 PM
OK, this shouldn't be too tough. How do I read one line at a time from a text file in Bash?
I'd like to do something like:
for i in list.txt
do
some_work_that_depends_on $i
done
I had hoped that this would read the file one line at a time and assign it to $i until it reached EOF, but it doesn't. It's been a while since I tried anything like this in the shell and I just can't remember how.
Thanx for any help.
marvin
04-02-2002, 06:21 PM
This should do it.
for line in $(cat file.txt); do
echo line: $line;
done
TheLinuxDuck
04-02-2002, 06:38 PM
Marvin:
Actually, that won't work as-is, because a for loop treats spaces as an individual item. So, your echo statement will print each space-delimited item as a line... You'll have to do some funk on it to get it to work correctly. My hack is this: When I cat the file, I replace all spaces with '\r's. That way, a line is treated as a whole line, only delimited by it's newline '\n'. And when I deal with the line later, I remove the '\r'.
This obviously won't work if the file could contain '\r's, but i don't see why a *nix file would.. (^=
Here is my addition:
for line in $(cat /etc/passwd | tr ' ' '\r' ); do
echo line: $line | tr '\r' ' '
done
TheLinuxDuck
04-02-2002, 06:39 PM
eflashj:
Here is the link for a really good bash HOW-TO. I use it all the time when I have questions.
http://linuxdoc.org/LDP/abs/html/
marvin
04-02-2002, 08:05 PM
Originally posted by TheLinuxDuck:
<STRONG>Marvin:
Actually, that won't work as-is, <snip> </STRONG>
OOPS :o Yes, you're right, stupid me didn't test it before I posted it... I'll go stand in the corner for a while :)
Strogian
04-02-2002, 09:08 PM
Or, you could just change the IFS variable to "<newline>" (i.e. IFS="
") That will make bash only split the expansion based on newlines. (IFS is normally set to "<space><tab><newline>") Hehe.. I JUST read that part of the bash man page, too. :D
TheLinuxDuck
04-03-2002, 10:26 AM
Originally posted by Strogian:
<STRONG>Or, you could just change the IFS variable to "<newline>" (i.e. IFS="
") That will make bash only split the expansion based on newlines. (IFS is normally set to "<space><tab><newline>") Hehe.. I JUST read that part of the bash man page, too. :D</STRONG>
I saw that too, but tried it, and it didn't work.. (^=
TheLinuxDuck
04-03-2002, 10:28 AM
Originally posted by marvin:
<STRONG>OOPS :o Yes, you're right, stupid me didn't test it before I posted it... I'll go stand in the corner for a while :)</STRONG>
(^= I've done that so many times.. don't worry, be happy, and eat cheese. (if you like cheese).
You should have seen how I was trying to do this before I saw yer first post! Whoa!
bwkaz
04-03-2002, 01:44 PM
Set IFS to this:
$'\n'
Then set it back (after you're done) to this:
$' \t\n'
That's dollar-sign, apostrophe, <stuff>, apostrophe.
Strogian
04-03-2002, 05:00 PM
Originally posted by TheLinuxDuck:
<STRONG> I saw that too, but tried it, and it didn't work.. (^=</STRONG>
Odd.. It works for me in a plain console. Lemme try it in a bash script.
Yep, works here too:
IFS="
"
joe="This is a really cool program.
It works perfectly.
I love it."
for line in $joe
do
echo "One Line Read"
done
Outputs:
One Line Read
One Line Read
One Line Read
I'm not sure how you'd work file input into that, but setting IFS does work. :) (I haven't gotten to the part that talks about what bwkaz is doing yet, but his way does look a tad bit cleaner ;))
TheLinuxDuck
04-03-2002, 05:05 PM
Word. I didn't do it right.... and that would explain why it didn't work right.. (^=
Qool.
As for setting IFS to newline and such, another way to do it would be to copy IFS into another variable, and then just reassign when done.
IFSCopy=$IFS
IFS=$'\n'
# do stuff
IFS=$IFSCopy
Something like that anyway.
Through the link I posted above, I found some example code that someone did.. it's basically a bash equivalent of C's string library. I was most impressed.. they converted most of the string function calls to a bash equivalent.. It's amazing what bash can do.
Word, yo's.. thanks for the pointers and info! (even though this thread wasn't my thread, I still learnededed some stuffs)
eflashj
04-04-2002, 12:30 PM
Thanx for all the help. I got it done, but not quite the way you all did. My solution looked like this:
num_lines=wc < INPUT_FILE | cut -d" " -f7
while [ $num_lines -gt 0 ]
do
line=`cat INPUT_FILE | tail -n $num_lines | head -n 1
do_some_work_based_on $line
num_lines=$(($num_lines-1))
done
[ 04 April 2002: Message edited by: eflashj ]