Art*_*ezy 2 shell awk grep sed
在最后一次匹配到文件末尾之后需要打印行。比赛的数量可以是任意的,而不是确定的。我有一些文字,如下所示。
MARKER
aaa
bbb
ccc
MARKER
ddd
eee
fff
MARKER
ggg
hhh
iii
MARKER
jjj
kkk
lll
Run Code Online (Sandbox Code Playgroud)
所需的输出是
jjj
kkk
lll
Run Code Online (Sandbox Code Playgroud)
是否将awk与RS和FS结合使用以获得所需的输出?
实际上,您可以使用awk(gawk)进行操作,而无需使用任何管道。
$ awk -v RS='(^|\n)MARKER\n' 'END{printf "%s", $0}' file
jjj
kkk
lll
Run Code Online (Sandbox Code Playgroud)
说明:
(^|\n)MARKER\nvia RS='(^|\n)MARKER\n',默认情况下为EOLchar'END{printf "%s", $0}'=>在文件的结尾,您打印整条生产线,如RS设置为(^|\n)MARKER\n,$0将包括所有的行,直到EOF。grep(GNU):
$ grep -zoP '(?<=MARKER\n)(?:(?!MARKER)[^\0])+\Z' file
jjj
kkk
lll
Run Code Online (Sandbox Code Playgroud)
说明:
-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
Run Code Online (Sandbox Code Playgroud)
说明:
n 跳到下一行h 用当前行替换保留空间H 做同样的事情,但不要替换,而是追加${x;p}在文件交换(x)的末尾保留空间和模式空间并打印(p)可以变成:
tac file | sed -n '/^MARKER$/q;p' | tac
Run Code Online (Sandbox Code Playgroud)
如果我们使用tac。
您可以尝试以下吗?
tac file | awk '/MARKER/{print val;exit} {val=(val?val ORS:"")$0}' | tac
Run Code Online (Sandbox Code Playgroud)
这种方法的好处是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).
Run Code Online (Sandbox Code Playgroud)