【问题标题】:How to search a multi-line pattern in a text and get the last occurrence?如何在文本中搜索多行模式并获取最后一次出现?
【发布时间】:2013-11-23 23:31:22
【问题描述】:
我需要在文件中查找 pgp 加密消息。它们以-----BEGIN PGP MESSAGE----- 开头,以-----END PGP MESSAGE----- 结尾。
到目前为止,我有这个:
$ tail -200 somefile | awk '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/'
它正在查找所有出现,但我只想要最后一个。
【问题讨论】:
标签:
linux
command-line
awk
【解决方案1】:
awk '
/-----BEGIN PGP MESSAGE-----/ {
inBlock = 1
block = ""
}
inBlock {
block = block $0 ORS
if (/-----END PGP MESSAGE-----/) {
inBlock = 0
}
}
END {
printf "%s", block
}
' somefile
【解决方案2】:
你可以使用 sed:
tail -200 somefile | sed -n '
# only consider lines between BEGIN and END
/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/ {
# if the beginning line, clear the hold space
/-----BEGIN PGP MESSAGE-----/{x;d}
# add the line to the hold space
H
};
# print the hold space at the end
${x;p}'
此 sed 注释(cmets 用于解释,实际命令中不需要),“BEGIN”和“END”之间的任何行都将添加到保留空间,每个“BEGIN”都会清除保留空间",然后在最后打印出来。
编辑:
为了完整起见,这里是不带 cmets 且在一行中的版本(与上面相同)
tail -200 somefile | sed -n '/-----BEGIN PGP MESSAGE-----/,/-----END PGP MESSAGE-----/{/-----BEGIN PGP MESSAGE-----/{x;d};H};${x;p}'
【解决方案3】:
BEGIN {
beginmsg = "-----BEGIN PGP MESSAGE-----"
endmsg = "-----END PGP MESSAGE-----"
}
$0 ~ beginmsg {
block = ""
}
beginmsg,endmsg {
block = block $0 ORS
}
END {
printf "%s", block
}