如何查找包含字符串的行,然后打印这些特定行和其他内容

spe*_*ong 18 command-line grep sed

我使用以下命令递归搜索多个文件,并在找到该字符串的每个文件中查找行号。

    grep -nr "the_string" /media/slowly/DATA/lots_of_files > output.txt
Run Code Online (Sandbox Code Playgroud)

输出如下:

    /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.
Run Code Online (Sandbox Code Playgroud)

如上所示,输出包括文件名、行号和该行中的所有文本,包括字符串。

我还想出了如何使用以下命令仅打印包含字符串的文件的特定行:

    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
Run Code Online (Sandbox Code Playgroud)

我通过读取行​​号和文件名手动创建了上述命令

这是我的问题。

Q1a

有没有办法将两个步骤合并为一个命令?我正在考虑将行号和文件名输入 sed 并打印该行。我对生成 grep 输出的顺序有问题。

Q1b

与上面相同,但还要打印包含字符串的行之前的 2 行和之后的 2 行(共 5 行)?我正在考虑将行号和文件名输入 sed 并以某种方式打印所有必需的行。

十分感谢。

che*_*rdt 18

如果我正确理解了这个问题,您可以使用一个 grep 命令来完成此操作。

对于 Q1a,您的grep输出可以使用 抑制文件名-h,例如:

grep -hnr "the_string" /media/slowly/DATA/lots_of_files > output.txt
Run Code Online (Sandbox Code Playgroud)

对于 Q1b,您的grep输出可以包括使用-Aand匹配行之前和之后的行-B,例如:

grep -hnr -A2 -B2 "the_string" /media/slowly/DATA/lots_of_files > output.txt
Run Code Online (Sandbox Code Playgroud)

输出将包含匹配项之间的分隔符,您可以使用 来抑制它--no-group-separator,例如:

grep -hnr -A2 -B2 --no-group-separator "the_string" /media/slowly/DATA/lots_of_files > output.txt
Run Code Online (Sandbox Code Playgroud)

请注意,输出使用不同的分隔符来匹配行 ( :) 和上下文行 ( -)。


Dop*_*oti 3

据我所知,你的第一个问题可以通过grep不同的方式来回答。当您向它发送文件列表(或使用-r或进行递归的目录-R)时,它将始终输出找到匹配项的文件以及行号。您可以使用如下结构来解决这个问题:

find /path/to/files -type f | xargs grep -n 'the_pattern'
Run Code Online (Sandbox Code Playgroud)

至于你的第二个问题,如果你想查看比赛之前和之后的行,你可以使用-C(for C ontext) 开关:

grep -C2 'pattern' /path/to/file # displays the two lines before and after a match
Run Code Online (Sandbox Code Playgroud)

相关的-C-A(for A fter) 和-B(for B before),它们分别只给出匹配之后或之前指定的行数。

您可以这样组合两个答案:

find /path/to/files -type f | xargs grep -n -C2 'the_pattern'
Run Code Online (Sandbox Code Playgroud)

至于你的问题sed,你给出的例子只有在你已经知道行号的情况下才有效。您还可以执行以下操作:

sed -n '/the_pattern/p' /path/to/files/*
Run Code Online (Sandbox Code Playgroud)

(但不会递归到子目录)