1828352 Members
3401 Online
109976 Solutions
New Discussion

Re: Looping question

 
SOLVED
Go to solution
Gary Glick
Frequent Advisor

Looping question

I'm trying to process a list of users in a file.
The format of the file is:
first_name last_name
The output from the following script

#!/bin/sh
for USER in `cat /scripts/scan/user2.list`
do
echo $USER
done

is
first_name
last_name
first_name
last_name
not
first_name last_name like I expected.

any ideas? I've looked through the forums a& I'm stumped. I'm not married to the for loop so any other suggestions are welcome.

Thank you

Gary
10 REPLIES 10
Pete Randall
Outstanding Contributor

Re: Looping question

I guess it must depend on the format of your input file, which, from the output, appears to be first name on one line, followed by last name on the next line. Can you confirm?


Pete

Pete
James R. Ferguson
Acclaimed Contributor
Solution

Re: Looping question

Hi Gary:

If your file contains separate fields, as you suggest it does, do:

while read FIRST LAST THE_REST
do
echo "${FIRST} and ${LAST}"
done < /scripts/scan/user2.list

...or:

while read LINE
do
echo "${LINE}"
done < /scripts/scan/user2.list

Regards!

...JRF...
Geoff Wild
Honored Contributor

Re: Looping question

for USER in `cat /scripts/scan/user2.list |awk '{print $0}'`

Rgds...Geoff
Proverbs 3:5,6 Trust in the Lord with all your heart and lean not on your own understanding; in all your ways acknowledge him, and he will make all your paths straight.
A. Clay Stephenson
Acclaimed Contributor

Re: Looping question

The script is doing just as I expect it you so one of us must be wrong. Essentially the for is parsing on any white space -- not just NL's.

cat "/scripts/scan/user2.list" | while read USER
do
echo "User: ${USER}"
done

If you actually want to separate the names then:

cat "/scripts/scan/user2.list" | while read FNAME LNAME
do
echo "Firstname: ${FNAME} Lastname: ${LNAME}"
done

The read statement also breaks on whitespace
up to a NL. The read statement has the characteristic that any remaining characters in the line are insterted into the last listed variable.
If it ain't broke, I can fix that.
Pete Randall
Outstanding Contributor

Re: Looping question

As James and Geoff point out (and I missed earlier), the blank delimited first and last names will be interpreted as separate users.


Pete

Pete
Sandman!
Honored Contributor

Re: Looping question

Hi Gary,

Could you paste a sample of the input file that you are trying to process. That would make things clearer as to the task you are trying to accomplish.

cheers!
Gary Glick
Frequent Advisor

Re: Looping question

It does look like it's parsing on the white space. I didn't know it would do that.
I'll try the suggestions listed.

Here's a sample of the input file


test testing
System PC
Wiley Coyote
Proxy PC
PC Support
IT Training

Thanks again.
Gary
Sandman!
Honored Contributor

Re: Looping question

Gary,

Doing a man on sh-posix will tell you that the field separator for shell input is the IFS (internal field separator) variable, which by default is set to blank space.

In your script you can reset it to something other than a space (colon perhaps) and then the results will be according to your expectations. Otherwise the shell is doing its job correctly by outputting the field one per line. For example...

=============================================
#!/bin/sh
IFS=":"
for USER in `cat /scripts/scan/user2.list`
do
echo $USER
done
=============================================

Make sure you reset the IFS back to its original value (blank space) otherwise it'll stay on for the remainder of your session and possibly impact other scripts or programs which expect default functionality from the shell.

No need to worry though if you are executing from a shell script as the spawned subshell would exit after script completion.

hope it helps!
James R. Ferguson
Acclaimed Contributor

Re: Looping question

Hi (again) Gary:

I am compelled to add a couple of comments regarding technique and efficiency.

The most economical appproach to reading a file in a shell script does *not* initiate a separate process to to so, as commonly seen with solutions involving 'cat'. It is more efficient to write:

while read LINE
do
...
done < inputfile

...than it is to write:

cat inputfile | while read LINE
...

The second point is an amplification os Sandman's reference to the IFS (Inter-Field Seperator).

Whenever you have a script in which you want to temporarily change the default value of IFS to something else, as for instance to set it to a colon character to parse the '/etc/password' file, a safe technique is to do this:

...
OLDIFS=${IFS}
IFS=":"
while read USER THE_REST
do
echo "I see ${USER}"
done < /etc/passwd
IFS=${OLDIFS}
...

Regards!

...JRF...
Gary Glick
Frequent Advisor

Re: Looping question

Wow, thank you all for your help. I did get my script working. Whe while loop ended up being the best solution for me.