当分配的分隔符出现两次时,IFS 会出现问题。一次在字符串中间,一次在字符串末尾

当分配的分隔符出现两次时,IFS 会出现问题。一次在字符串中间,一次在字符串末尾

以下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 变体才在最后一个变量中包含分隔符。ksh88bosh

  • ksh93bash包含输入的未修改的其余部分,以防存在多个尾随分隔符。

POSIX 声明:

If there are fewer vars than fields, the last var shall
be set to a value comprising the following elements:

但无法解释两个分隔符之间的空字段是否算作一个字段。因此,根据我的理解,ksh88ksh93行为可能是正确的,因此,确切的行为似乎是不确定的。

相关内容