用bash从单行变量中回显有效的证书文件

时间:2018-12-09 16:35:58

标签: awk sed echo

我将证书存储在一行中的环境变量中,如下所示:

$EXAMPLE=-----BEGIN CERTIFICATE----- line1 line2 line3 etc.. -----END CERTIFICATE-----

如何从此环境var转到文件,其中所有行都转换为换行符,除了----- BEGIN CERTIFICATE -----和----- END CERTIFICATE --- -零件?

我知道我可以做到:

$ echo "$EXAMPLE" | tr ' ' '\n' > ca.pem

它将所有空格替换为换行符,但这将导致:

-----BEGIN
CERTIFICATE-----
line1
line2
line3
etc..
-----END
CERTIFICATE-----

几乎在那里...但是带有'-----'的BEGIN和END行不应中断。有人对此有干净的解决方案吗?不管是sed,awk,grep还是其他:)

谢谢!

4 个答案:

答案 0 :(得分:3)

对于未导出的变量名,请不要使用大写形式,以避免与已导出名和/或内置名冲突。使用GNU awk作为第三个参数match()和$('.timespanbutton').each(function() { var slotName = "timespanbutton" + $(this).val(); // new var declare var timespanObject.timespanName = slotName; timespanArray.push(timespanObject); }); 的简写\S

[^[:space:]]

以上脚本适用于任何输入。您应该尝试提出脚本可能无法运行的输入,以便能够针对任何提议的解决方案进行测试,以查看其是否真正起作用,因为提出一个可以从一个特定样本输入生成预期输出的脚本很简单,并且要想出一种适用于所有情况的解决方案要困难得多。

例如,要测试的一个重要且显而易见的示例是:

$ example='-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----'
$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
line1
line2
line3
-----END CERTIFICATE-----

即在4行证书本身中恰好同时/不幸地是以下字符串的地方:

  • 第1行= $ example='-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- -----END CERTIFICATE-----'
  • 第2行= -----BEGIN
  • 第3行= CERTIFICATE-----
  • 第4行= -----END

输出应为:

CERTIFICATE-----

因此,如果任何提议的解决方案不能正确处理该问题,则不要使用该解决方案。

当前没有其他答案可以正确处理此问题:

破坏者的awk:

$ printf '%s\n' "$example" |
awk 'match($0,/^(\S+ \S+)(.*)(\S+ \S+)$/,a){gsub(/ /,ORS,a[2]); print a[1] a[2] a[3]}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE-----
-----END
CERTIFICATE-----
-----END CERTIFICATE-----

saichovsky的seds和管道:

$ printf '%s\n' "$example" |
awk '
match($0,/- .* -/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/- | -/,"",val)
  gsub(OFS,ORS,val)
  print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)
}'
-----BEGIN CERTIFICATE-----
-----BEGIN
CERTIFICATE---------END
CERTIFICATE-----
-----END CERTIFICATE-----

anubhava的perl:

$ printf '%s\n' "$example" |
sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'
-----BEGIN CERTIFICATE-----
-----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----END CERTIFICATE-----

答案 1 :(得分:2)

使用perl可以将正则表达式与(*SKIP)(*F)一起使用:

s='-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----'
perl -pe 's/-+(?:BEGIN|END) CERTIFICATE-+(*SKIP)(*F)|\h+/\n/g' <<< "$s"

-----BEGIN CERTIFICATE-----
line1
line2
line3
-----END CERTIFICATE-----

正则表达式...(*SKIP)(*F)|\h+会跳过-BEGIN CERTIFICATE-或结尾-END CERTIFICATE-的开头,同时匹配1个以上的水平空白,以换行符代替。


perl不可用的情况下,这里是一个awk解决方案(我想让它也能在非GNU awk上工作时有点冗长):

awk '{
   out=""
   for (i=1; i<=NF; i++)
      out = sprintf("%s%s%s", out, $i, 
      (i<NF && $i~/^-+(BEGIN|END)$/ && $(i+1)~/^CERTIFICATE-+$/ ? " " : "\n"))
   printf "%s", out
}' <<< "$s"

答案 2 :(得分:0)

可以请您尝试一次(考虑到您的Input_file与所示示例相同)。

y


说明: 现在添加了以上代码的说明。

EXAMPLE="-----BEGIN CERTIFICATE----- line1 line2 line3 -----END CERTIFICATE-----"
echo "$EXAMPLE" | awk '
match($0,/- .* -/){
  val=substr($0,RSTART,RLENGTH)
  gsub(/- | -/,"",val)
  gsub(OFS,ORS,val)
  print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)
}'

答案 3 :(得分:-1)

echo $EXAMPLE | sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'

应该给你想要的东西。