for-while loop issue

sup experts..i had a script which was bugging me..was hoping someone could point out the issue here

Input file: space separated 2 columns

I wanted to print out the 2 columns after assigning them to variables ( bascially the same output but iterate through line by line ). The code worked with a while loop but not with a for loop.

Code with for loop:

for i in `cat tmp.dat `
          do
         c=`echo $i|awk -F " "  '{ print $1 }'`
        p=`echo $i|awk -F " " '{ print $2 }'`
         echo $c,$p
          echo -------
         done

Output ( wrong):

While loop code:

while read i
        do
         c=`echo $i|awk -F " "  '{ print $1 }'`
        p=`echo $i|awk -F " " '{ print $2 }'`
        echo $c,$p
         echo -------
        done < tmp.dat

Output(correct):

shell /bin/ksh
Linux lonrs00845 2.6.9-42.0.8.ELsmp #1 SMP Tue Jan 23 12:49:51 EST 2007 x86_64 x86_64 x86_64 GNU/Linux

Was hoping someone could tell me why the for loop is printing all first columns first.. followed by the 2nd columns ..but the while loop correctly prints:
col1, col2
col1, col2..etc ( bascially the input file again )

i put in the IFS as "\n" as well..
thanks all ..much appreciated...is not a code as such..something i was trying out and cudnt figure out the cause.

Hi.

The man page explains it:

for vname [ in word ... ] ;do list ;done
              Each  time  a for command is executed, vname is set to the next word taken from the in word list.

That's to say your $i variable would get one word at a time, not the line, as you expected.

The while loop is the better way, and can be shorter still:

while read c p; do
  echo $c,$p
  echo -------
done < tmp.dat

First off, you get a Useless Use of Cat Award. You can make your program faster and less buggy by doing loops like

while read INPUT
do
done < file.txt

instead of

for INPUT in `cat file.txt`
do
done

since by politely reading the lines one at a time, you won't ever run into the limits of a shell size variable, and won't need to consume the entire size of the list in memory at once.

The read builtin also lets you separate both by IFS and by line, while the 'for' loop tries to jam it all in one big line.

while read A B
do
done < input.txt

thanks for the early reply guys..
@scottn -- if the for loop read it as 2 words, I should get the output as:

col1
col2
col1
col2
but i get it as:

col1
col1
col1
col1
col2
col2...etc
and i should still get multiple line separators instead of the single one i am getting at the output..

@corona..shouldnt the IFS take care of splitting the for loops into 2 variables as well?

and ya..ill take the award anyway..somethin better than nothin i guess :stuck_out_tongue:

you're reading the entire file into memory as one ugly clump then splitting the whole clump instead of line by line. As such, it doesn't understand the concept of 'lines'. If you ever get a line with THREE things in it by accident, it will throw the entire rest of your processing into chaos and disarray.

Also, you're reading things one at a time, not two at a time.

Have you tried my solution? It works.

Hi.

I can't possibly see how you got that output with the code you posted.

Did your script do anything else with the output before you posted it?

hi,

@scott...i jus pasted the code from unix into the forum.. i never used shells on linux ...been using ksh on AIX since long so i figured prob somethin i dont noe here..
shells cant be diff on 2 systems ( at least as much as the output)..
I didnt write a script as such...was jus running the commands from the shell..trying things out..

will try it again tomo on the office system whr i got the issue and update post again..else lemme noe if you guys can provide some insight..

coronas soln wud work im sure..

---------- Post updated at 10:03 PM ---------- Previous update was at 11:19 AM ----------

Hi,

Update on the issue:

Opened new shell and executed for loop: get multi line-separators.

Ran again after setting export IFS="\n"

Wondering how IFS messes the output like this?

Please post what your program actually is so we can help you.