按模式剥离文件的最后一部分 - 从链中删除最后一个证书

Strip last part of file by pattern - remove last certificate from chain

我有一个像这样的 SSL 证书链

-----BEGIN CERTIFICATE-----
MIICPjCCAeSgAwIBAgIRALMMpKnhRM2C7mnKI/rl8ggwCgYIKoZIzj0EAwIwgY4x
CERT1
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIjCCAsegAwIBAgIOAMjnPM1wShDmOWUELuIwCgYIKoZIzj0EAwIwgagxCzAJ
CERT2
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIDCCAsWgAwIBAgIOAMjnPL8JUbVSmpMadWUwCgYIKoZIzj0EAwIwbDELMAkG
CERT3
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAqygAwIBAgIFFRCCEwYwCgYIKoZIzj0EAwIwgZQxFDASBgNVBAoMC0Ft
CERT4
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDNjCCAtugAwIBAgIJAKpBxYNyH8biMAoGCCqGSM49BAMCMIGUMRQwEgYDVQQK
CERT5
-----END CERTIFICATE-----

我需要从中删除最后一个证书。

在 MacOS/BSD 命令 split 上有标志 -p 以按模式拆分,我使用它:

cat cert | split -p "-----BEGIN CERTIFICATE-----" 
cat xa{a,b,c,d}

我相信在 Linux 上也有一条命令可以在一行中执行此操作,但是在 Ubuntu 上命令 split 无法按模式拆分。

我需要使用标准 linux 命令来完成这项工作,例如我标记的命令。

这个 GNU Sed 解决方案应该足够了

sed -zE 's/(.*\n)-----BEGIN CERTIFICATE-----.*//' your_input

其中 -E 允许使用 (…) 而不是 \(…\) 来捕获某些东西,而 -z (在 GNU Sed 中可用)将整个输入视为嵌入 \ns.

的单个长字符串

因此,第一个 .* 尽可能多地匹配(并捕获它,连同紧随其后的 \n,因此它可以通过使用 [=18 在替换中引用它=]), 只要它后面跟着 \n-----BEGIN CERTIFICATE----- 和它后面的任何其他内容 (第二个 .*).

单独使用任何 awk:

$ awk '/-----BEGIN CERTIFICATE-----/{printf "%s", rec; rec=""} {rec=rec [=10=] ORS}' file
-----BEGIN CERTIFICATE-----
MIICPjCCAeSgAwIBAgIRALMMpKnhRM2C7mnKI/rl8ggwCgYIKoZIzj0EAwIwgY4x
CERT1
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIjCCAsegAwIBAgIOAMjnPM1wShDmOWUELuIwCgYIKoZIzj0EAwIwgagxCzAJ
CERT2
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIDCCAsWgAwIBAgIOAMjnPL8JUbVSmpMadWUwCgYIKoZIzj0EAwIwbDELMAkG
CERT3
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAqygAwIBAgIFFRCCEwYwCgYIKoZIzj0EAwIwgZQxFDASBgNVBAoMC0Ft
CERT4
-----END CERTIFICATE-----

或者如果你有 tac:

$ tac file | awk 'f; /-----BEGIN CERTIFICATE-----/{f=1}' | tac
-----BEGIN CERTIFICATE-----
MIICPjCCAeSgAwIBAgIRALMMpKnhRM2C7mnKI/rl8ggwCgYIKoZIzj0EAwIwgY4x
CERT1
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIjCCAsegAwIBAgIOAMjnPM1wShDmOWUELuIwCgYIKoZIzj0EAwIwgagxCzAJ
CERT2
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDIDCCAsWgAwIBAgIOAMjnPL8JUbVSmpMadWUwCgYIKoZIzj0EAwIwbDELMAkG
CERT3
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDBjCCAqygAwIBAgIFFRCCEwYwCgYIKoZIzj0EAwIwgZQxFDASBgNVBAoMC0Ft
CERT4
-----END CERTIFICATE-----

使用 GNU awk 使用 gensub 您可以仅根据显示的示例尝试遵循、编写和测试。

awk -v RS="" -v regex="(.*)\n(-----BEGIN CERTIFICATE-----.*)" '
{
  print gensub(regex,"\1","1",[=10=])
}' Input_file