将 grep 上下文限制为 N 个字符

将 grep 上下文限制为 N 个字符

我必须 grep 一些行长度超过几千个字符的 JSON 文件。如何限制 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

答案1

尝试使用这个:

grep -r -E -o ".{0,10}wantedText.{0,10}" *

-E告诉您要使用扩展正则表达式

-o告诉您只想打印匹配项

-rgrep 正在文件夹中递归查找结果

正则表达式:

{0,10}告诉您要打印多少个任意字符

代表任意字符(字符本身并不重要,重要的是它们的编号)

编辑:哦,我明白了,约瑟夫推荐的解决方案与我几乎相同:D

答案2

cut使用标志将标准输出通过管道传输-b;您可以指示 grep 的输出每行仅包含 1 到 400 字节。

grep "foobar" * | cut -b 1-400

答案3

使用 GNU grep

N=10; grep -roP ".{0,$N}foo.{0,$N}" .

解释:

  • -o=> 仅打印您匹配的内容
  • -P=> 使用 Perl 风格的正则表达式
  • 正则表达式表示将 0 与$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/
    ' {} \;

解释:

由于我们不能再依赖grepGNU grep,所以我们使用find递归搜索文件(-rGNU 的操作grep)。对于找到的每个文件,我们执行 Perl 代码片段。

Perl 开关:

  • -n逐行读取文件
  • -l打印时去掉每行末尾的换行符并放回去
  • -e将以下字符串视为代码

Perl 代码片段本质上与grep.首先将变量设置$N为所需的上下文字符数。这意味着BEGIN{}它仅在执行开始时执行一次,而不是每个文件中的每一行执行一次。

如果正则表达式替换有效,则对每一行执行的语句将打印该行。

正则表达式:

  • 在行 ( ) 的开头延迟匹配任何旧的事物1^.*?,然后是.{0,$N}与本例相同的grep情况,然后是foo另一个.{0,$N},最后延迟匹配任何旧的事物,直到行 ( ) 的末尾.*?$
  • 我们将其替换为$ARGV:$1.$ARGV是一个神奇的变量,它保存当前正在读取的文件的名称。$1是括号匹配的内容:本例中的上下文。
  • 两端的惰性匹配是必需的,因为贪婪匹配会吃掉之前的所有字符foo而不会匹配失败(因为.{0,$N}允许匹配零次)。

1也就是说,最好不要匹配任何内容,除非这会导致整个匹配失败。简而言之,匹配尽可能少的字符。

答案4

取自:http://www.topbug.ne​​t/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))}"

假设脚本保存为grepl,那么grepl pattern file_with_long_lines应该显示匹配的行,但匹配字符串周围只有 10 个字符。

相关内容