鉴于文本正文可以跨越不同数量的行,我需要使用grep,sed或awk解决方案来搜索相同模式的许多文件,得到身体的最后一句话。
文件可以包含这样的格式,其中我想要的单词可以命名为
call function1(input1,
input2, #comment
input3) #comment
returning randomname1,
randomname2,
success3
call function1(input1,
input2,
input3)
returning randomname3,
randomname2,
randomname3
call function1(input1,
input2,
input3)
returning anothername3,
randomname2, anothername3
我需要打印出结果
success3
randomname3
anothername3
另外,我需要一些关于每个的文件名和行信息。
我试过
pcregrep -M 'function1.*(\s*.*){6}(\w+)$' filename.txt
这太贪心了,我仍然需要打印出特定的分组值,而不是整个模式。在我的示例代码中返回的单词function1
将始终以此命名,并且可以在我的表达式中进行硬编码。
答案 0 :(得分:5)
代码块的最后一句话
使用awk的记录分隔符RS
在块中拆分文件。记录将被定义为文本块,记录由双新行分隔。
记录由字段组成,每两个连续字段由空格或单个换行符分隔。
现在我们要做的就是打印每条记录的最后一个字段,产生以下代码:
awk 'BEGIN{ FS="[\n\t ]"; RS="\n\n"} { print $NF }' file
说明:
FS
这是字段分隔符,设置为换行符,制表符或空格:[\n\t ]
。RS
这是记录分隔符,设置为doulbe换行符:\n\n
print $NF
这将打印带有索引$
的字段NF
,该字段是包含字段数的变量。因此,这将打印最后一个字段。注意:要捕获文件应以双换行结尾的所有段落,可以使用以下方法预处理文件轻松实现:$ echo -e '\n\n' >> file
。
基于评论的替代解决方案
更优雅的简单解决方案如下:
awk -v RS='' '{ print $NF }' file
答案 1 :(得分:3)
以下awk解决方案如何:
awk 'NF == 0 {if(last) print last; last=""} NF > 0 {last=$NF} END {print last}' file
$NF
获取最后一个"字"的值其中NF
代表字段数。然后last
变量总是将最后一个单词存储在一行上,如果它遇到一个空行,则打印出来,表示段落的结尾。
匹配function1
条件的新版本。
awk 'NF == 0 {if(last && hasF) print last; last=hasF=""}
NF > 0 {last=$NF; if(/function1/)hasF=1}
END {if(hasF) print last}' filename.txt
答案 2 :(得分:2)
这将生成您从发布的输入文件中显示的输出:
$ awk -v RS= '{print $NF}' file
success3
randomname3
anothername3
如果你想像你提到的那样打印FILENAME和行号,那么这可能是你想要的:
$ cat tst.awk
NF { nr=NR; last=$NF; next }
{ prt() }
END { prt() }
function prt() { if (nr) print FILENAME, nr, last; nr=0 }
$ awk -f tst.awk file
file 6 success3
file 13 randomname3
file 20 anothername3
如果这样做不符合您的要求,请编辑您的问题,以提供更清晰,更真实的代表性和准确的样本输入和预期输出。
答案 3 :(得分:1)
这是贝类的awk解决方案的perl版本(加上关键字):
perl -00 -nE '/function1/ and /returning/ and say ((split)[-1])' file
或者,有一个正则表达式:
perl -00 -nE '/^(?=.*function1)(?=.*returning).*?(\S+)\s*$/s and say $1' file
但关键是-00
选项,它一次读取一个段落。