Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process each output line in a loop?

Tags:

grep

bash

shell

People also ask

How can I loop over the output of a shell command?

#!/bin/bash while IFS= read -a oL ; do { # reads single/one line echo "${oL}"; # prints that single/one line }; done < <(ps -ewo pid,cmd,etime | grep python | grep -v grep | grep -v sh); unset oL; Note: You can use any simple or complex command/command-set inside the <(...) which may have multiple output lines.

How do I grep a line in Linux?

The grep command syntax is simply grep followed by any arguments, then the string we wish to search for and then finally the location in which to search. 1. Search test1 for the string steve using grep. The search criteria is case sensitive so ensure that you're searching correctly.

How do bash scripts work?

A bash script is a series of commands written in a file. These are read and executed by the bash program. The program executes line by line. For example, you can navigate to a certain path, create a folder and spawn a process inside it using the command line.


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)

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.


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

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


For those looking for a one-liner:

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

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"

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