将grep输出限制为短行


8

我经常使用grep查找具有特定条目的文件,如下所示:

grep -R 'MyClassName'

好消息是它返回文件及其内容,并将找到的字符串标记为红色。不好的是,我还有很大的文件,整个文本都写在一个大的单行中。现在,在这些大文件中查找文本时,grep输出过多。有没有一种方法可以将输出限制为例如左右两个单词?还是将输出限制为左右30个字母?


3
通过管道发送结果cut
Rinzwind

因此,假设您要查找的模式位于位置50,但是您说只需要30个字母,那么您想做什么?忽略该行还是将其包含在输出中但修剪它?您到底要限制什么?搜索还是行本身?
Sergiy Kolodyazhnyy

1
@Rinzwind我不太了解您要使用什么实现cut,因为它仅按定界符或字符数进行拆分。尽管当我找到一条线时,MyClassName它可能在行中的任何位置,而并不总是在同一位置。此外,字符的正面和背面可能会有变化,这打破了用定界符分割字符的可能性。
苏格拉底

1
@SergiyKolodyazhnyy MyClassName找到一个正线时,我想作为结果获得文件名和左右两个x字符。x是我提供的任何数字,例如30。其余文件内容将被忽略。这是为了获得匹配文件的上下文并限制过载。
苏格拉底

1
@Rinzwind会建议使用什么类型的自定义分隔符的cut,如果有三个文件有以下输入:oiadfaosuoianavMyClassNameionaernaldfajd/(/&%%§%/(§(/MyClassName&((/$/$/(§/$&public class MyClassName { public static void main(String[] args) { } }
苏格拉底

Answers:


15

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输入文本,然后再将其grepping,例如:

fold -sw 80 input.txt | grep ...

-s选项将使fold推词移至下一行,而不会在其间打断。

或使用其他方式根据输入的结构将输入分成几行。(例如,SU帖子处理的是JSON,因此使用jqetc.进行漂亮的打印和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
好的,可以。似乎Regex是一种有效的方法,所以谢谢。尽管处理时间相当长。如上面的帖子所述,不使用Regex则需要4.912秒,而使用Regex的则需要3m39.312s。
苏格拉底

1
@Socrates看看我上面添加的awk方法是否效果更好
muru

1
fold仅当您确定搜索到的字符串没有出现在边框上时,才可以使用该方法,否则它将被隐藏grep
Melebius

1
@muru感谢您与的建议gawk。不幸的是,find在我的系统上执行时,建议的命令输出的是随机的东西,没有文件名。此外,我不够流利,awk无法正确分析命令。目前,正则表达式与结合起来grep解决问题可能不是很快,但可靠。再次,非常感谢。
苏格拉底

1
@Socrates我想我设法解决了awk命令。我的心智模型在使用哪行RT和前缀等方面是错误的。
muru

1

结合使用仅匹配和其他一些选项(参见下文),可能非常接近您要寻找的内容,而没有其他答案中提到的regex处理开销

grep -RnHo 'MyClassName'
  • n数字输出,显示匹配的行号
  • H文件名,在比赛行的开头显示文件名
  • o仅匹配,仅显示数学字符串,而不显示整行

确实可以更快地找到结果,但是缺少信息。显示了文件路径,显示了行号,但文本输出仅是我的初始搜索MyClassName。因此,缺少上下文。
苏格拉底

grep -RnHo "MyClassName"grep -Rno "MyClassName"具有相同的输出。
苏格拉底

@Socrates的输出在同一目录中没有H时是不一样的
Robert Riedl '18

-o如果正则表达式具有可变部分,则该标志可能会很有趣。对于固定的字符串,每次打印都没有用。OP最有可能对近期环境感兴趣。
Melebius

1
@Socrates,是真的,缺少上下文,但是我认为那是重点?限制输出?您可以通过在(-B 1)之前或(-A 1)之后添加行来再次添加上下文。对不起,我没有更多帮助。
罗伯特·里德尔
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.