首页 文章

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

提问于
浏览
0

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

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

我如何从这个环境var转到一个文件,其中所有行都被转换为换行符,除了----- BEGIN CERTIFICATE -----和----- END CERTIFICATE ----- parts ?

我知道我可以这样做:

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

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

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

差不多......但是带有'-----'的BEGIN和END行不应该破坏 . 任何人都有一个干净的解决方案吗?无论是sed,awk,grep,等等:)

谢谢!

4 回答

  • -1

    不要对非导出的变量名使用全部大写,以避免与导出和/或内置名称冲突 . 使用GNU awk为第3个arg匹配()和 \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-----
    

    以上脚本适用于任何输入 . 你应该尝试提出脚本可能失败的输入,以便能够测试任何提议的解决方案,看看它是否真的有效,因为提出一个脚本可以从一个特定的样本输入产生预期的输出,更难以提出适用于所有情况的解决方案 .

    例如,要测试的一个重要而明显的例子是:

    $ example='-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE----- -----END CERTIFICATE----- -----END CERTIFICATE-----'
    

    也就是说,在4行证书本身内恰好/恰巧是这些字符串:

    • 第1行= -----BEGIN

    • 第2行= CERTIFICATE-----

    • 第3行= -----END

    • 第4行= 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-----
    -----BEGIN
    CERTIFICATE-----
    -----END
    CERTIFICATE-----
    -----END CERTIFICATE-----
    

    因此,如果任何建议的解决方案无法正确处理,那么不要使用该解决方案 .

    其他当前发布的答案都没有正确处理:

    Ravinder's awk:

    $ 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-----
    

    saichovsky's seds plus pipe:

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

    anubhava's perl:

    $ perl -pe 's/(?:BEGIN|END) CERTIFICATE(*SKIP)(*F)|\h+/\n/g' <<< "$example"
    -----BEGIN CERTIFICATE-----
    -----BEGIN CERTIFICATE-----
    -----END CERTIFICATE-----
    -----END CERTIFICATE-----
    
  • 2

    您可以尝试一次(考虑到您的Input_file与显示的样本相同) .

    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)
    }'
    


    Explanation: 现在添加上述代码的说明 .

    echo "$EXAMPLE" | awk '          ##Printing value of example variable and passing its output to awk command then.
    match($0,/- .* -/){              ##using match to match REGEX to match it from - .* to - if match found then do following.
      val=substr($0,RSTART,RLENGTH)  ##creating val here whose value is substring is starting from RSTART to RLENGTH.
      gsub(/- | -/,"",val)           ##Using gsub to substitute to substitute - space OR space - with NULL in variable val.
      gsub(OFS,ORS,val)              ##Substituting OFS with ORS in variable val here.
      print substr($0,1,RSTART) ORS val ORS substr($0,RSTART+RLENGTH-1)  ##Printing substring from 1 to RSTART then val and substring RSTART+RLENGTH-1 with ORS values.
    }'
    
  • 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"
    
  • 0
    echo $EXAMPLE | sed 's/- /-\n/g; s/ -/\n-/g' | sed '/CERTIFICATE/! s/ /\n/g'
    

    应该给你你想要的 .

相关问题