我经常使用 grep 来查找具有特定条目的文件,如下所示:
grep -R 'MyClassName'
好处是它会返回文件及其内容,并将找到的字符串标记为红色。坏处是,我还有一些大文件,其中的整个文本都写在一行中。现在 grep 在这些大文件中查找文本时输出太多。有没有办法将输出限制为例如左右各 5 个单词?或者将输出限制为左右各 30 个字母?
答案1
grep
本身只有基于行的上下文选项。另一种选择是这篇 SU 帖子:
一种解决方法是启用“仅匹配”选项,然后使用 RegExp 的功能来 grep 比文本更多的内容:
grep -o ".\{0,50\}WHAT_I_M_SEARCHING.\{0,50\}" ./filepath
当然,如果您使用颜色突出显示,您可以随时再次 grep 以仅为真正的匹配着色:
grep -o ".\{0,50\}WHAT_I_M_SEARCHING.\{0,50\}" ./filepath | grep "WHAT_I_M_SEARCHING"
作为另一种选择,我建议fold
文本,然后对其进行 grep,例如:
fold -sw 80 input.txt | grep ...
该-s
选项将把fold
单词推到下一行,而不是在中间断行。
或者使用其他方法根据输入的结构将输入拆分成行。(例如,SU 帖子处理了 JSON,因此使用jq
等进行漂亮打印和grep
...或仅使用jq
其本身进行过滤...会比上面给出的两种替代方案中的任何一种都好。)
这个 GNU awk 方法可能更快:
gawk -v n=50 -v RS='MyClassName' '
FNR > 1 { printf "%s: %s\n",FILENAME, p prt substr($0, 0, n)}
{p = substr($0, length - n); prt = RT}
' input.txt
- 告诉 awk 根据我们感兴趣的模式 (
-v RS=...
) 和上下文中的字符数 (-v n=...
)拆分记录 - 第一条记录(
FNR > 1
)之后的每一条记录都是 awk 找到的与模式匹配的记录。 - 因此,我们打印上
n
一行的尾随字符(p
)和n
当前行的前导字符(substr($0, 0, n)
),以及上一行的匹配文本(即prt
)- 我们设定
p
并prt
后打印,所以我们设置的值被下一个线 RT
是一种 GNUism,这就是为什么它是 GNU awk 特有的。
- 我们设定
对于递归搜索,也许:
find . -type f -exec gawk -v n=50 -v RS='MyClassName' 'FNR>1{printf "%s: %s\n",FILENAME, p prt substr($0, 0, n)} {p = substr($0, length-n); prt = RT}' {} +
答案2
使用唯一匹配与其他一些选项结合(见下文),可能非常接近您所寻求的,而没有其他答案中提到的正则表达式的处理开销
grep -RnHo 'MyClassName'
- n数字输出,显示匹配的行号
- H文件名,在匹配行的开头显示文件名
- o仅匹配,仅显示匹配的字符串,而不是整行