How to find lines containing a string and then printing those specific lines and something else

command linegrepsed

I use the following command to recursively search multiple files and find the line number in each file in which the string is found.

    grep -nr "the_string" /media/slowly/DATA/lots_of_files > output.txt

The output is as follows:

    /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt:3:the_string
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:6:the_string is in this sentence.
    /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt:9:the_string is in this sentence too.

As shown above, the output includes the filename, line number and all the text in that line including the string.

I have also figured out how to print just the specific lines of a files containing the string using the following command:

    sed '3!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_3.txt > print.txt
    sed '6!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt
    sed '9!d' /media/slowly/DATA/lots_of_files/lots_of_files/file_7.txt >> print.txt

I created the above commands manually by reading the line numbers and filenames

Here's my question.

Q1a

Is there a way to combine both steps into one command? I'm thinking piping the line number and the filename into sed and printing the line. I'm having a problem with the order in which the grep output is generated.

Q1b

Same as above but also print the 2 lines before and 2 lines after the line containing the string (total of 5 lines)? I'm thinking piping the line number and the filename into sed and printing all the required lines somehow.

Big thanks.

Best Answer

If I am understanding the question correctly, you can accomplish this with one grep command.

For Q1a, your grep output can suppress the filename using -h, e.g.:

grep -hnr "the_string" /media/slowly/DATA/lots_of_files > output.txt

For Q1b, your grep output can include lines preceding and following matched lines using -A and -B, e.g.:

grep -hnr -A2 -B2 "the_string" /media/slowly/DATA/lots_of_files > output.txt

The output will contain a separator between matches, which you can suppress with --no-group-separator, e.g.:

grep -hnr -A2 -B2 --no-group-separator "the_string" /media/slowly/DATA/lots_of_files > output.txt

Note that the output uses a different delimiter for matching lines (:) and context lines (-).

Related Question