需要在最后一次匹配到文件末尾之后打印行。比赛的数量可以是任意的,而不是确定的。我有一些文字,如下所示。
MARKER
aaa
bbb
ccc
MARKER
ddd
eee
fff
MARKER
ggg
hhh
iii
MARKER
jjj
kkk
lll
所需的输出是
jjj
kkk
lll
我将awk与RS和FS一起使用以获得所需的输出吗?
答案 0 :(得分:6)
实际上,您可以使用awk
(gawk)进行操作,而无需使用任何管道。
$ awk -v RS='(^|\n)MARKER\n' 'END{printf "%s", $0}' file
jjj
kkk
lll
说明:
(^|\n)MARKER\n
将记录分隔符定义为RS='(^|\n)MARKER\n'
,默认情况下为EOL
字符'END{printf "%s", $0}'
=>在文件末尾,您将打印整行,因为RS
被设置为(^|\n)MARKER\n
,$0
将包括所有行,直到EOF 。
grep
(GNU):
$ grep -zoP '(?<=MARKER\n)(?:(?!MARKER)[^\0])+\Z' file
jjj
kkk
lll
说明:
-z
使用ASCII NUL字符作为分隔符-o
仅打印匹配项-P
激活perl模式(?<=MARKER\n)(?:(?!MARKER)[^\0])+\Z
在这里https://regex101.com/r/RpQBUV/2/
sed
方法:
sed -n '/^MARKER$/{n;h;b};H;${x;p}' file
jjj
kkk
lll
说明:
n
跳至下一行h
用当前行替换保留空间H
执行相同的操作,但不要替换,而是添加${x;p}
在文件交换(x
)结束时保留空间和图案空间并打印(p
)可以变成:
tac file | sed -n '/^MARKER$/q;p' | tac
如果我们使用tac
。
答案 1 :(得分:3)
请您尝试以下。
tac file | awk '/MARKER/{print val;exit} {val=(val?val ORS:"")$0}' | tac
此方法的好处是awk
只会读取Input_file的最后一块(实际上,这是awk
的第一个块,tac
反向打印之后),然后退出。
说明:
tac file | ##Printing Input_file in reverse order.
awk '
/MARKER/{ ##Searching for a string MARKER in a line of Input_file.
print val ##Printing variable val here. Because we need last occurrence of string MARKER,which has become first instance after reversing the Input_file.
exit ##Using exit to exit from awk program itself.
}
{
val=(val?val ORS:"")$0 ##Creating variable named val whose value will be keep appending to its own value with a new line to get values before string MARKER as per OP question.
}
' | ##Sending output of awk command to tac again to make it in its actual form, since tac prints it in reverse order.
tac ##Using tac to make it in correct order(lines were reversed because of previous tac).
答案 2 :(得分:1)
这可能对您有用(GNU sed):
sed -nz 's/.*MARKER.//p' file
这使用贪婪删除所有行,包括最后一次出现的MARKER
。
答案 3 :(得分:0)
您也可以尝试Perl
$ perl -0777 -ne ' /.*MARKER(.*)/s and print $1 ' input.txt
jjj
kkk
lll
$
答案 4 :(得分:0)
tac fun.log | sed "/MARKER/Q" | tac