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

Awk 按模式剥离文件的最后一部分-从链中删除最后一个证书,awk,sed,ack,Awk,Sed,Ack,我有一个像这样的SSL证书链 ----开始证书----- MIICPJCCAESGAWIBAGIRALMPKNHRM2C7MNKI/RL8GGWCGYIKOZJ0EAWIWGY4X 证书1 -----结束证书----- -----开始证书----- MIIDIJCCASEGAWIBAGIOAMJNPM1WSHDMOWUELUIWCGYIKOZJ0EAWIWGAGXCZAJ 证书2 -----结束证书----- -----开始证书----- MIIDDCCASWGAWIBAGIOAMJNPL8JU

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

----开始证书-----
MIICPJCCAESGAWIBAGIRALMPKNHRM2C7MNKI/RL8GGWCGYIKOZJ0EAWIWGY4X
证书1
-----结束证书-----
-----开始证书-----
MIIDIJCCASEGAWIBAGIOAMJNPM1WSHDMOWUELUIWCGYIKOZJ0EAWIWGAGXCZAJ
证书2
-----结束证书-----
-----开始证书-----
MIIDDCCASWGAWIBAGIOAMJNPL8JUBVSMPMADWUCGYIKOZJ0EAWIWBDELMAKG
证书3
-----结束证书-----
-----开始证书-----
MIIDBJCCAQYGAWIBAGIFFRCEWCGYIKOZJ0EAWIWGZQXFDASBGNVBAOMC0FT
证书4
-----结束证书-----
-----开始证书-----
Miidnjccatugawaibagijakpbxynyh8bimaogccqgsm49bamcmigumrqwegydvqk
证书5
-----结束证书-----
我需要把它的最后一张证书去掉

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

cat cert | split -p "-----BEGIN CERTIFICATE-----" 
cat xa{a,b,c,d}
我相信在Linux上也有一个命令可以在一行中完成,但是在Ubuntu上,
split
命令不能按模式进行分割


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

这个基于GNU的解决方案应该足够了

sed-zE的/(.*\n)---开始证书------.*/\1/'您的\u输入
其中,
-E
允许使用
(…)
而不是
\(…)
来捕获某些内容,
-z
(在GNU Sed中可用)是将整个输入作为一个嵌入了
\n
s的长字符串处理

因此,第一个
*
尽可能匹配(并捕获它,以及它后面的
\n
,以便它可以使用
\1
在替换中引用它),只要它后面跟着
\n------开始证书------
和它后面的任何内容(第二个
*
).

单独使用任何awk:

$ awk '/-----BEGIN CERTIFICATE-----/{printf "%s", rec; rec=""} {rec=rec $0 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",$0)
}' Input_file

它会删除最后一个
----END证书---
,但请确保它能正常工作。谢谢你。@kyb,你不想移除它吗?请在您的问题中包含所需的输出。此命令输出4个证书,去掉第5个证书。这就是我要找的。但是第四个证书看起来坏了,因为它没有------结束证书------。我想在输出中看到4个有效证书。(当然很容易用
echo
手动添加)@kyb我已经修复了它(老实说,根据Ed的建议)。基本上,我有
(.*)\n
,它没有捕获,因此删除了EOF处的最后一个换行符,这是一些VS编辑器所需要的(VS=非常愚蠢);将其更改为
(.*\n)
将保留捕获组中的最后一个换行符,并因此保留在输出中,从而使这些编辑器感到高兴。是的。现在,它的工作如预期。非常感谢。我以前不知道
-z
。你知道OP对这个输出的抱怨吗?(见他们在我的问题下的评论。)@Enrico我怀疑他们正在使用编辑器或其他工具来验证丢弃/隐藏输出的最后一行的输出,因为它没有以换行结束(我知道你现在已经修复了),所以对他们来说,最后一行丢失了。oooow,我以为他们指的是原来的最后一行!他们显然是指您在我的代码中更正的错误。那么,再次谢谢你。不客气。我只是猜测这就是它的意义,当然,但它似乎是有可能的,我想不出任何其他事情!据我所知,RS=”“表示“slurp模式”,因此$0包含完整的输入文件。对吗?@kyb no,
RS=“”
(或
RS=”
)表示“段落模式”`其中记录由空行分隔
RS='^$'
(如果您的awk版本支持多字符RS)用于“slurp模式”,其中$0包含完整的输入文件。当输入不包含任何空行(这可能是您的情况)时,它们的行为类似,除非使用
RS=”“
$0将不包含文件中的最后一个换行,而使用
RS='\0'
则会。要查看差异,请尝试
echo 7 | awk-v RS=''{print'}'
echo 7 | awk-v RS='^$'{print'}'
并注意第一个输出中
>
之前的换行符。@EdMorton,谢谢您在这里澄清我的理解是错误的。