给定的文本正文可以跨越不同行数,我需要使用 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
我需要将结果打印为
成功3
随机名称3
另一个名字3
我还需要一些关于每个的文件名和行信息。
我试过了
pcregrep -M 'function1.*(s*.*){6}(w+)$' filename.txt
这太贪婪了,我仍然需要打印出特定的分组值,而不是整个模式。 示例代码中的单词 function1
和返回将始终按 this 命名,并且可以在我的表达式中进行硬编码。
代码块的最后一个字
使用 awk 的记录分隔符RS
将文件拆分为块。记录将被定义为文本块,记录由双换行符分隔。
记录由字段组成,每个连续的两个字段由空格或单个换行符分隔。
现在我们要做的就是打印每条记录的最后一个字段,生成以下代码:
awk 'BEGIN{ FS="[nt ]"; RS="nn"} { print $NF }' file
解释:
-
FS
这是字段分隔符,设置为换行符、制表符或空格:[nt ]
。 -
RS
这是记录分隔符,设置为杜尔贝换行符:nn
-
print $NF
这将打印带有索引NF
的字段$
,这是一个包含字段数的变量。因此,这将打印最后一个字段。
注意:要捕获所有段落,文件应以双换行符结尾,这可以通过使用:$ echo -e 'nn' >> file
对文件进行预处理来轻松实现。
基于注释的替代解决方案
一个更优雅和简单的解决方案如下:
awk -v RS='' '{ print $NF }' file
以下 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
这将从您发布的输入文件中生成您显示的输出:
$ awk -v RS= '{print $NF}' file
success3
randomname3
anothername3
如果你想打印文件名和行号,就像你提到的,那么这可能是你想要的:
$ 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
如果这不符合您的要求,请编辑您的问题以提供更清晰、更真实、更具有代表性和准确的示例输入和预期输出。
这是 Shellfish 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
选项,它一次读取一个段落的文件。