lolaferrari
asked on
IFS on /etc/passwd
If you want to run the below on /etc/passwd file why does it not stop at the end of the first line. At then end of the first line there isn't any :
!/bin/bash
# seven fields from /etc/passwd stored in $f1,f2...,$f7
#
while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
do
echo "User $f1 use $f7 shell and stores files in $f6 directory."
done < /etc/passwd
!/bin/bash
# seven fields from /etc/passwd stored in $f1,f2...,$f7
#
while IFS=: read -r f1 f2 f3 f4 f5 f6 f7
do
echo "User $f1 use $f7 shell and stores files in $f6 directory."
done < /etc/passwd
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
IFS is the "Internal Field Separator". It simply sets the character that is used for defining the separator between fields.
The while loop simply loops until it runs out of data.
If you need to break out of a loop, you can use 'break'.
The while loop simply loops until it runs out of data.
If you need to break out of a loop, you can use 'break'.
ASKER
Sometimes you have to set the IFS back to it's default in order that it reads another line from the file in order that it processes the newline. However, you don't have to do this for /etc/passwd and I wondered why. The last line at the end of the first line in /etc/passwd isn't a : but yet it continues to read the next line.
What do you mean by "last line at the end of the first line" and how would that be relevant to whether the next line is read?
What do you want to do?
If you want to stop at the first line, you can either break out of the loop, or take head -1
Or why loop at all if you don't want more than one line?
What do you want to do?
If you want to stop at the first line, you can either break out of the loop, or take head -1
Or why loop at all if you don't want more than one line?
>> but yet it continues to read the next line
It continues because you give it the whole file to process ( < /etc/passwd ). As I mentioned already, you have 7 fields on each line, each separated by the separator you specify (colon).
So the script is behaving the way it is specified. If you mean different behaviour, then you have to give the script less data, like one line only (head -1 /etc/passwd) as suggested above.
It continues because you give it the whole file to process ( < /etc/passwd ). As I mentioned already, you have 7 fields on each line, each separated by the separator you specify (colon).
So the script is behaving the way it is specified. If you mean different behaviour, then you have to give the script less data, like one line only (head -1 /etc/passwd) as suggested above.
ASKER
Hi ozo i'm just trying to parse the whole input file which is a csv. My script only reads the first line in the csv input file and then stops.
I'm stumped with this! I've tried so many variations of reading my inputfile but the script only reads the first line in the file.
I have a input file that looks like this
<hostname>,<os version>,<comment>,<user>
....
fonzy,SunOS 5.10,NOT-CORRECT,izywizzy
.....
read -r and printf seems not to work on this OS so stuck with read and print.
I've read every line in the file and output it to od to see if there was a new line at the end of every line and there was.
== this example works for the first line in the file but doesn't read any other line from the input file beyond the first line==
while IFS=',' read f1 f2 f3 f4;do
OS=$(echo $f2 | awk '{print $1}')
if [[ "$OS" == "SunOS ]]; then
do something with $f1 and $f4
else
if [[ "$OS" == "RHEL" ]]; then
do something with $f1 and $f4
done < inputfile
==this example doesn't
cat input | awk -F',' '{print $1 $2 $3 $4}' | while read f1 f2 f3 f4; do
echo "$f1-$f2-$f3-$f4"
if [[ "$f2" == "SunOS" ]]; then
.....
however, the output isn't correct since $2 in the input file has a space in it and the echo output shows the field displayed like this
fonzy-SunOS-5.10-NOT-CORRE CT izywizy
I'm stumped with this! I've tried so many variations of reading my inputfile but the script only reads the first line in the file.
I have a input file that looks like this
<hostname>,<os version>,<comment>,<user>
....
fonzy,SunOS 5.10,NOT-CORRECT,izywizzy
.....
read -r and printf seems not to work on this OS so stuck with read and print.
I've read every line in the file and output it to od to see if there was a new line at the end of every line and there was.
== this example works for the first line in the file but doesn't read any other line from the input file beyond the first line==
while IFS=',' read f1 f2 f3 f4;do
OS=$(echo $f2 | awk '{print $1}')
if [[ "$OS" == "SunOS ]]; then
do something with $f1 and $f4
else
if [[ "$OS" == "RHEL" ]]; then
do something with $f1 and $f4
done < inputfile
==this example doesn't
cat input | awk -F',' '{print $1 $2 $3 $4}' | while read f1 f2 f3 f4; do
echo "$f1-$f2-$f3-$f4"
if [[ "$f2" == "SunOS" ]]; then
.....
however, the output isn't correct since $2 in the input file has a space in it and the echo output shows the field displayed like this
fonzy-SunOS-5.10-NOT-CORRE
For one thing, you are missing closing " and fi
ASKER
ah the script runs ok - just a typos because I've no access to the server so it's just from memory so syntactically it's correct
ASKER
while IFS=, read f1 f2 f3 f4;do
OS=$(echo $f2 | awk '{print $1}')
echo "$f1 $f2 $f3 $f4"
if [[ "$f2" == "RHEL" ]]; then
do something $OS $f4
else
if if [[ "$f2" == "SunOS" ]]; then
do something $OS $f4
else
if ... [[....
fi
fi
fi
done < inputfile
OIFS=$'\n'
while IFS=, read f1 f2 f3 f4;do
OS=$(echo $f2 | awk '{print $1}')
echo "$f1 $f2 $f3 $f4"
if [[ "$f2" == "RHEL" ]]; then
do something $OS $f4
else
if if [[ "$f2" == "SunOS" ]]; then
do something $OS $f4
else
if ... [[....
fi
fi
fi
IFS=$OIFS
done < inputfile
OS=$(echo $f2 | awk '{print $1}')
echo "$f1 $f2 $f3 $f4"
if [[ "$f2" == "RHEL" ]]; then
do something $OS $f4
else
if if [[ "$f2" == "SunOS" ]]; then
do something $OS $f4
else
if ... [[....
fi
fi
fi
done < inputfile
OIFS=$'\n'
while IFS=, read f1 f2 f3 f4;do
OS=$(echo $f2 | awk '{print $1}')
echo "$f1 $f2 $f3 $f4"
if [[ "$f2" == "RHEL" ]]; then
do something $OS $f4
else
if if [[ "$f2" == "SunOS" ]]; then
do something $OS $f4
else
if ... [[....
fi
fi
fi
IFS=$OIFS
done < inputfile
ASKER
I was trying to understand the logic of why what I try with /etc/passwd works but the same logic doesn't apply if I use another input file which looks the same as /etc/passwd with the exception that the IFS is a comma instead of a :
I'm sorry for the confusion. I still don't understand why the logic of below works for password file when it done work for other files. After it reads the first line in /etc/passwd the last field in password doesn't have a : but yet the while loop goes around to read the next line in the password file. I have a script that uses a different delimiter but it will only read the first line in the file and apparently others have had a similar problem where you have to set the delimiter back to its default. I tried that but it still doesn't work.
while IFS=':' read -r f1 f2 f3 ......;do
.....
....
done < /etc/passwd
I'm sorry for the confusion. I still don't understand why the logic of below works for password file when it done work for other files. After it reads the first line in /etc/passwd the last field in password doesn't have a : but yet the while loop goes around to read the next line in the password file. I have a script that uses a different delimiter but it will only read the first line in the file and apparently others have had a similar problem where you have to set the delimiter back to its default. I tried that but it still doesn't work.
while IFS=':' read -r f1 f2 f3 ......;do
.....
....
done < /etc/passwd
User root use /bin/bash shell and stores files in /root directory.
User bin use /sbin/nologin shell and stores files in /bin directory.
User daemon use /sbin/nologin shell and stores files in /sbin directory.
User adm use /sbin/nologin shell and stores files in /var/adm directory.
User lp use /sbin/nologin shell and stores files in /var/spool/lpd directory.
User sync use /bin/sync shell and stores files in /sbin directory.
User shutdown use /sbin/shutdown shell and stores files in /sbin directory.
User halt use /sbin/halt shell and stores files in /sbin directory.
...