如何获取一对字符串最后一次出现之间的文本

How to get the text between the last occurrence of a pair of strings

我需要提取最后一次出现的单词“-----BEGIN CERTIFICATE-----”和最后一次出现的单词“-----END CERTIFICATE--”之间的文本---".

输入:

some other data above this line
-----BEGIN CERTIFICATE-----
a
b
c
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
d
e
f
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
g
h
i
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
j
k
l
-----END CERTIFICATE-----
some other data below this

预期输出:

-----BEGIN CERTIFICATE-----
j
k
l
-----END CERTIFICATE-----

输出应包括 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE-----

我的方法:

我尝试了以下命令,但它给我的输出没有 -----BEGIN CERTIFICATE----- 和 -----END CERTIFICATE-----

openssl s_client -showcerts -connect localhost:443 </dev/null | sed -n 'H; /^-----BEGIN CERTIFICATE-----/h; ${g;p;}' |sed -e '1d' -e '/-----END CERTIFICATE-----/q' |sed '$ d' > mycertfile.pem

上述命令的输出:

j
k
l

当我听到“获取 last XYZ”时,我认为“反转文件并获取 first XYZ”:反转输入,并在 first“BEGIN CERT”出现时 sed quit,然后 re-reverse 数据:

openssl ... | tac | sed '/BEGIN CERT/q' | tac

由于在最后一行 ---END 之后还有内容,请尝试以下变体:

openssl ... | tac | sed -n '/---END/,/---BEGIN/ p; /---BEGIN/ q' | tac

只打印由证书标记限定的行范围,并在第一个之后退出。


另一种方法:使用 perl 读取整个输入,使用正则表达式捕获所有 BEGIN/END 块,并打印最后一个。

openssl ... | perl -0777 -nE '
  @certs = m/^-----BEGIN .+?^-----END .+?$/gms;
  say $certs[-1];
'