问题:
如果没有 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
输出当前行号。输出的行号是文件中的行号。=
sed
Line
请注意,虽然第二个正则表达式似乎与文件中的换行符匹配,但事实并非如此。它与内部缓冲区中的换行符匹配,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 时重置。