以下IFS
命令没有给出预期的输出:
$ IFS='=' read -r key value <<< "fram-saml-idp-signing-certificate=MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM="; echo "KEY: ${key}";echo "VALUE: ${value}"
输出:
KEY: fram-saml-idp-signing-certificate
VALUE: MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM
缺少最后一个等号 (=)。
然而,以下命令给出了正确的预期输出:
$ IFS='=' read -r key value <<< "fram-saml-idp-signing-certificate=MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM=="; echo "KEY: ${key}";echo "VALUE: ${value}"
输出:
KEY: fram-saml-idp-signing-certificate
VALUE: MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM==
这是一个错误吗IFS
?如何修改第一个命令,以便=
在末尾有一个等号 ( ) 时获得正确的输出?
答案1
健壮且可移植的解决方案应该是:使用一个变量,及其相应的变量(参数?)扩展。
str="fram-saml-idp-signing-certificate=MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM="
key=${str%%=*} # select the string up to the first =
value=${str#"$key="} # take all that is not the variable above.
echo "KEY: ${key}";echo "VALUE: ${value}"
适用于所有 Bourne shell(ksh、bash、zsh,旧的 Bourne shell 本身除外)。
细节
“分词”的规则相当复杂(详细信息请阅读下面的相关链接,有很多“特殊情况”)。
两个(或多个)尾随分隔符是不是删除所有外壳。但在 dash、bash 和 ksh 中删除了一个尾随分隔符(但 zsh 不会删除它)。
选择。
稳健的解决方案在bash中是使用正则表达式匹配:
str='fram-saml-idp-signing-certificate=MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM='
re='^([^=]*)=(.*)';
[[ $str =~ $re ]] && key="${BASH_REMATCH[1]}" value="${BASH_REMATCH[2]}";
echo "KEY: ${key}";echo "VALUE: ${value}"
这将(正确)打印:
KEY: fram-saml-idp-signing-certificate
VALUE: MIIDYTCCAkmifzlwq5yziqyU04eP4wLr3cM=
有关的
答案2
对于以单个分隔符结尾的最后一个字段,所有已知的 shell 都同意并删除该分隔符。
如果有多个尾随分隔符,则情况视情况而定,并且您是否可以预期特定的行为是值得怀疑的。
仅当后面跟随非空字段时,
Bourne Shell
、 、和ksh88
的 POSIX 变体才在最后一个变量中包含分隔符。ksh88
bosh
ksh93
并bash
包含输入的未修改的其余部分,以防存在多个尾随分隔符。
POSIX 声明:
If there are fewer vars than fields, the last var shall
be set to a value comprising the following elements:
但无法解释两个分隔符之间的空字段是否算作一个字段。因此,根据我的理解,ksh88
和ksh93
行为可能是正确的,因此,确切的行为似乎是不确定的。