在文件中搜索多行正则表达式的匹配(不使用 pcregrep)

在文件中搜索多行正则表达式的匹配(不使用 pcregrep)

问题:

如果没有 pcregrep,如何在文件中找到多行正则表达式的匹配项?

我需要查找/打印每次出现的位置。

不幸的是,pcregrep 不存在,我无权安装它。其他替代方案grep perl sed python等等。

用于搜索的正则表达式的示例是:

Text\nLine

语境:

一个脚本在几十个文件中提供了数百 MB 的结构化文本,但遗憾的是缺少一些行(由于多种原因)。我确实需要检查这些行在哪里丢失,从而搜索前一行和后一行的顺序。

Text
Missing //this line is sometimes missing.
Line

编辑:

可能的输入

示例.txt

Text
Missing
Line

Text
Missing
Line

Text
Line

Text
Missing
Line

可能的输出:

示例.txt,第 10 行

一些没有成功的尝试:

pcregrep 
    # command not found
apt-get install pcregrep 
    # no permission, no su credentials, distro don't provide pcregrep, outdated sources, customer does not want changes on the serve, etc.
sed -r 's#(Text\nLine)#\1#' ./* 
    # print all lines, not only matches, no indication of file or line, etc.
grep 'Text\nLine' ./* 
    # Does not works on multi-lines
sed -n '/Text/,/Line/{p}' ./* 
    # Not the same regex, does not indicate result lines, etc.

答案1

Unix 工具通常是面向行的,因此无法使用标准工具箱对多行输入应用正则表达式。

sed可以以能够检测您正在查找的行的方式处理文件,但我们严格使用对各个行的操作来执行此操作:

$ sed -n '/^Text/{N;/^Text\nLine/=;D;}' file
10

sed脚本查找Text行开头的字符串。找到后,它将下一行添加到其缓冲区中,并在\n中间插入一行。

如果缓冲区现在匹配,则使用中的命令^Text\nLine输出当前行号。输出的行号是文件中的行号。=sedLine

请注意,虽然第二个正则表达式似乎与文件中的换行符匹配,但事实并非如此。它与内部缓冲区中的换行符匹配,N当我们从文件中读取下一行时,我们使用命令将其放在那里。

如果您想将其应用于多个文件,您可能会在循环中使用它:

for name in pattern; do
    printf 'Processing %s...\n' "$name"
    sed -n '/^Text/{N;/^Text\nLine/=;D;}' "$name"
done

其中pattern是与您感兴趣的文件相匹配的普通文件名通配模式。

答案2

如果vim安装了,您可以在ex以下模式下使用它:

vim -e -s -c 'argdo g/^Text\nLine/#' -c q ./*.txt

另请参阅z给出上下文的命令。

vim -e -s -c 'argdo g/^Text\nLine/z#.5' -c q ./*.txt

但这不会打印文件名。一个不太有效的perl方法可能是:

perl -l -0777 -ne 'while (/Text\nLine/g) {
   print "$ARGV, line " . ++(() = $` =~ /\n/g)}' ./*.txt

答案3

 perl -ne 'eof and $. = 0 or /^Text/ && ($_ .= <>) =~ /^Line/m && print "$ARGV: $.\n"' ./*

这将打印文件名以及发生匹配的行号。

此外,行计数器 ($.) 在到达每个文件的 eof 时重置。

相关内容