How to process each output line in a loop?

BashShellGrep

Bash Problem Overview


I have a number of lines retrieved from a file after running the grep command as follows:

var=`grep xyz abc.txt`

Let’s say I got 10 lines which consists of xyz as a result.

Now I need to process each line I got as a result of the grep command. How do I proceed for this?

Bash Solutions


Solution 1 - Bash

One of the easy ways is not to store the output in a variable, but directly iterate over it with a while/read loop.

Something like:

grep xyz abc.txt | while read -r line ; do
    echo "Processing $line"
    # your code goes here
done

There are variations on this scheme depending on exactly what you're after.

If you need to change variables inside the loop (and have that change be visible outside of it), you can use process substitution as stated in fedorqui's answer:

while read -r line ; do
    echo "Processing $line"
    # your code goes here
done < <(grep xyz abc.txt)

Solution 2 - Bash

You can do the following while read loop, that will be fed by the result of the grep command using the so called process substitution:

while IFS= read -r result
do
    #whatever with value $result
done < <(grep "xyz" abc.txt)

This way, you don't have to store the result in a variable, but directly "inject" its output to the loop.


Note the usage of IFS= and read -r according to the recommendations in BashFAQ/001: How can I read a file (data stream, variable) line-by-line (and/or field-by-field)?:

> The -r option to read prevents backslash interpretation (usually used > as a backslash newline pair, to continue over multiple lines or to > escape the delimiters). Without this option, any unescaped backslashes > in the input will be discarded. You should almost always use the -r > option with read. > > In the scenario above IFS= prevents trimming of leading and trailing > whitespace. Remove it if you want this effect.

Regarding the process substitution, it is explained in the bash hackers page:

> Process substitution is a form of redirection where the input or > output of a process (some sequence of commands) appear as a temporary > file.

Solution 3 - Bash

For those looking for a one-liner:

grep xyz abc.txt | while read -r line; do echo "Processing $line"; done

Solution 4 - Bash

I would suggest using awk instead of grep + something else here.

awk '$0~/xyz/{ //your code goes here}' abc.txt

Solution 5 - Bash

Without any iteration with the --line-buffered grep option:

your_command | grep --line-buffered "your search"

Real life exemple with a Symfony PHP Framework router debug command ouput, to grep all "api" related routes:

php bin/console d:r | grep --line-buffered "api"

Solution 6 - Bash

Iterate over the grep results with a while/read loop. Like:

grep pattern filename.txt | while read -r line ; do
    echo "Matched Line:  $line"
    # your code goes here
done

Solution 7 - Bash

Often the order of the processing does not matter. GNU Parallel is made for this situation:

grep xyz abc.txt | parallel echo do stuff to {}

If you processing is more like:

grep xyz abc.txt | myprogram_reading_from_stdin

and myprogram is slow then you can run:

grep xyz abc.txt | parallel --pipe myprogram_reading_from_stdin

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionXYZ_LinuxView Question on Stackoverflow
Solution 1 - BashMatView Answer on Stackoverflow
Solution 2 - BashfedorquiView Answer on Stackoverflow
Solution 3 - BashlaurentView Answer on Stackoverflow
Solution 4 - BashJulien GrenierView Answer on Stackoverflow
Solution 5 - BashNicolas BonniciView Answer on Stackoverflow
Solution 6 - BashAbhi kmView Answer on Stackoverflow
Solution 7 - BashOle TangeView Answer on Stackoverflow