Lets say you want to add line numbers to a text file. For example, you want to see this file:
The quick brown fox jumps over the lazy dog
… displayed on your screen list this:
1 The quick brown fox 2 jumps over the 3 lazy dog
Of course, you could use cat -n if you’re using cat and want line numbers, but if you want to, say, add a 4 space indent to the output of iwconfig, the following technique will work.
First, we run the program / script and capture the output:
output=$(iwconfig 2>/dev/null)
Here we’re running iwconfig in a subshell and capturing the output. In this case, I’m redirecting stderr to /dev/null, otherwise iwconfig returns lines like lo no wireless extensions. up through the subshell to the shell thats calling the bash script. I don’t want this so I’m throwing it out.
Next, we loop through the output using a for loop:
for LINE in ${output} ; do
echo ${LINE}
done
Running this will not get us the output we’re expecting, it will return each space-separated word/phrase on it’s own line. If we are still talking about the pangram above, we would see:
The quick brown fox jumps over the lazy dog
The problem is, the IFS (Internal Field Separator) contains the space character.
(Quick Aside)
To see what the IFS is, type:
echo -n "$IFS" | hexdump
My IFS contains 0×09, 0×20, 0×0a (tab, space and newline respectively).
(End Aside)
We can change the $IFS in our script (to only contain the newline character) which lets us iterate through the output where separated by newlines.
First, we save the original IFS and define the newline IFS:
OIFS="${IFS}"
NIFS=$'\n'
Next we set the IFS to our newline IFS:
IFS="${NIFS}"
Then, we loop through the output (in the loop we reset the IFS incase we expect it to include the space, etc. and then set it to newline IFS before our next iteration)
for LINE in ${output} ; do
IFS="${OIFS}"
echo "---- ${LINE}"
IFS="${NIFS}"
done
Lastly, we reset the IFS:
IFS="${OIFS}"
The final code looks like this:
output=$(iwconfig 2>/dev/null)
OIFS="${IFS}"
NIFS=$'\n'
IFS="${NIFS}"
for LINE in ${output} ; do
IFS="${OIFS}"
echo "---- ${LINE}"
IFS="${NIFS}"
done
IFS="${OIFS}"
… and we get what we had hoped:
---- The quick brown fox ---- jumps over the ---- lazy dog
In closing, it should be noted that I’ve done this a few different ways (including splitting the output with awk / sed) but I like the simplicity of this method. I may try to find the other methods and write them up to if I get some time.
P.S. If you ever need to reset your IFS but don’t want to close the terminal, type this:
IFS=$'\n\t '
RSS Feed
I’ve been looking everywhere for something like this. There are so many examples on the web that, for whatever reason, didn’t work for me. Thank You!!!