我必须对一些行长度超过几千个字符的 JSON 文件进行 grep。如何限制 grep 在匹配的左侧和右侧显示最多 N 个字符的上下文?除了 grep 之外的任何工具都可以,只要它在常见的 Linux 包中可用。
这将是示例输出,对于虚构的 grep 开关?:
$ grep -r foo *
hello.txt: Once upon a time a big foo came out of the woods.
$ grep -? 10 -r foo *
hello.txt: ime a big foo came of t
Run Code Online (Sandbox Code Playgroud)
Jos*_* R. 32
使用 GNU grep
:
N=10; grep -roP ".{0,$N}foo.{0,$N}" .
Run Code Online (Sandbox Code Playgroud)
解释:
-o
=> 仅打印您匹配的内容-P
=> 使用 Perl 风格的正则表达式$N
字符,foo
然后是 0 到$N
字符。如果您没有 GNU grep
:
find . -type f -exec \
perl -nle '
BEGIN{$N=10}
print if s/^.*?(.{0,$N}foo.{0,$N}).*?$/$ARGV:$1/
' {} \;
Run Code Online (Sandbox Code Playgroud)
解释:
由于我们不能再依赖于grep
GNU grep
,我们使用find
来递归搜索文件(-r
GNU的动作grep
)。对于找到的每个文件,我们执行 Perl 片段。
Perl 开关:
-n
逐行读取文件-l
去掉每行末尾的换行符,打印时放回去-e
将以下字符串视为代码Perl 片段在本质上与grep
. 它首先将变量设置为$N
您想要的上下文字符数。这BEGIN{}
意味着这仅在执行开始时执行一次,而不是对每个文件中的每一行执行一次。
如果正则表达式替换有效,则为每一行执行的语句将打印该行。
正则表达式:
^.*?
然后是.{0,$N}
这种grep
情况,foo
然后是另一个.{0,$N}
,最后懒惰地匹配任何旧事物,直到行 ( .*?$
)的末尾。$ARGV:$1
。$ARGV
是一个神奇的变量,它保存正在读取的当前文件的名称。$1
是括号匹配的内容:本例中的上下文。foo
而不会匹配失败(因为.{0,$N}
允许匹配零次)。1也就是说,不要匹配任何东西,除非这会导致整体匹配失败。总之,匹配尽可能少的字符。
Een*_*oku 31
尝试使用这个:
grep -r -E -o ".{0,10}wantedText.{0,10}" *
Run Code Online (Sandbox Code Playgroud)
-E表示您想使用扩展的正则表达式
-o告诉,你只想打印匹配
-r grep 正在文件夹中递归查找结果
正则表达式:
{0,10}告诉您要打印多少个任意字符
. 代表任意字符(字符本身在这里并不重要,只是它们的编号)
编辑:哦,我明白了,约瑟夫推荐的解决方案与我几乎相同:D
Eri*_*ski 20
将标准输出cut
与-b
标志连接;您可以将 grep 的输出指示为每行仅字节 1 到 400。
grep "foobar" * | cut -b 1-400
Run Code Online (Sandbox Code Playgroud)
摘自: http: //www.topbug.net/blog/ 2016/08/18/truncate-long-matching-lines-of-grep-a-solution-that-preserves-color/ 和 https://stackoverflow。 com/a/39029954/1150462
建议的方法".{0,10}<original pattern>.{0,10}"
非常好,除了突出显示颜色经常混乱之外。我创建了一个具有类似输出的脚本,但颜色也被保留:
#!/bin/bash
# Usage:
# grepl PATTERN [FILE]
# how many characters around the searching keyword should be shown?
context_length=10
# What is the length of the control character for the color before and after the matching string?
# This is mostly determined by the environmental variable GREP_COLORS.
control_length_before=$(($(echo a | grep --color=always a | cut -d a -f '1' | wc -c)-1))
control_length_after=$(($(echo a | grep --color=always a | cut -d a -f '2' | wc -c)-1))
grep -E --color=always "$1" $2 | grep --color=none -oE ".{0,$(($control_length_before + $context_length))}$1.{0,$(($control_length_after + $context_length))}"
Run Code Online (Sandbox Code Playgroud)
假设脚本保存为grepl
,那么grepl pattern file_with_long_lines
应该显示匹配的行,但匹配字符串周围只有 10 个字符。