"${line//END}" != "$line" - 它是做什么的

"${line//END}" != "$line" - what does it do

所以我得到了 API 调用包含 PEM 证书(其中很多)的文件的结果,如下所示:

-----BEGIN CERTIFICATE-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAA
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
BBB
-----END CERTIFICATE-----


-----BEGIN CERTIFICATE-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAssssssssssssssssssssssssssssssssssssssssssssss
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdddddd
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAssss
-----END CERTIFICATE-----

在@user2856925 的帮助下在这里回答 (https://serverfault.com/a/718751) 我开始运行我的脚本,它应该获得每个证书的到期日期。

while read line
do
    if [ "${line//END}" != "$line" ]; then
        txt="$txt$line\n"
        printf -- "$txt" | openssl x509 -enddate -noout  | cut -d "=" -f 2
        txt=""
    else
        txt="$txt$line\n"
    fi
done < /path/to/bundle/file

现在虽然这个东西可以满足我的要求,但理解它会是完美的,这样我就可以在其他脚本中使用它。

那我们开始做题吧。 "${line//END}" 是做什么的?什么是 // 在字符串上,它正在检查 END 字是否包含在变量行中??!

I 运行 bash -x 并看到变量 txt 被添加到下一行,直到找到 END CERTIFICATE 然后 printf 行是 运行。所以在这一行 txt="$txt$line\n" 之后它回到 while?? 这将解释 txt="" 行,该行正在清空变量,以便下一个证书出现。

但是为什么我们需要 else txt="$txt$line\n"??

该脚本还会忽略证书之间的所有那些空格 2 个或更多个或根本没有空格,或者如果证书格式正确,它就可以正常工作,这很棒,我不是在抱怨,但它是怎么做到的?

做一些基本测试。

$: line='-----END CERTIFICATE-----'
$: echo $line
-----END CERTIFICATE-----
$: echo "${line//END}"
----- CERTIFICATE-----

从上面使用 oguz ismail's excellent link -

"${line//END}" 是字符串替换,取 $line 的值并用 string[= 替换 pattern 37=].

诚然,手册页可能有点迟钝。基本上,结构是在 left/open 卷曲内部,紧跟在要解析的变量名称之后,你放了一个斜杠来告诉解析器这是一个模式 match/replace。由于第一个字段是 match/replace 的模式,而空模式通常没有意义,因此如果下一个字符也是未转义的斜线,那么它会使扫描成为全局(它通常只适用于第一次命中)。

也就是说END是搜索模式。没有给出替换模式,因此使用 none - 它被替换为任何内容。

[ "${line//END}" != "$line" ] 则表示“尝试删除所有出现的 END,然后查看是否有任何更改。”它有效,但就我个人而言,我不喜欢这种结构。您可以只使用搜索 --

if [[ "$line" =~ END ]] # check for END

但我喜欢 case 语句。

while read line
do case "$line" in
   *END*) txt="$txt$line\n"
          printf -- "$txt" | openssl x509 -enddate -noout  | cut -d "=" -f 2
          txt=""
   ;;
   *) txt="$txt$line\n"
   ;;
   esac
done < /path/to/bundle/file

将保留其他调整,而不是您所要求的。 :)