【问题标题】:IFS change with Bash 4.2IFS 随着 Bash 4.2 的变化
【发布时间】:2014-07-24 09:21:40
【问题描述】:

运行这些命令会得到预期的结果

$ bash --version
GNU bash, version 4.1.11(2)-release

$ foo=(111 222 333)

$ IFS=, cat <<< "${foo[*]}"
111,222,333

然而,在 Bash 4.2 中,IFS 值被忽略了

$ bash --version
GNU bash, version 4.2.0(1)-release

$ foo=(111 222 333)

$ IFS=, cat <<< "${foo[*]}"
111 222 333

造成这种差异的原因是什么?

我在这里找到了答案

http://lists.gnu.org/archive/html/bug-bash/2014-03/msg00065.html

看起来这一直是个错误。根据切特的说法, 重定向不应该访问临时环境 (在这种情况下为IFS

【问题讨论】:

  • @fedorqui spooky,我在 GNU bash, version 4.2.45(2)-release (x86_64-slackware-linux-gnu) 上,可以重现 OP 的行为
  • 转载GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)。输出为111 222 333
  • 对于那些感兴趣的人,这是 bash 4.2 的更新日志:github.com/sunny256/bash/blob/master/CWRU/changelog 一定有一些解释,因为它是从 4.​​1 到 4.2 时发生的变化。
  • 这也可能与 stackoverflow.com/q/20144593/1126841 松散相关(因为对这里的字符串和 IFS 的适当支持似乎是一个持续的过程)。

标签: bash ifs


【解决方案1】:

我发现 4.2 的行为是正确的,因为分词应该在评估作业之前首先发生:

IFS=, cat <<< "${foo[*]}"

我相信 IFS 的新值应该只影响cat 而不是&lt;&lt;&lt; "${foo[*]}"

正确的做法是

IFS=, eval 'cat <<< "${foo[*]}"'

对于保守的方法,我们可以使用函数:

function t { cat <<< "${foo[*]}"; }
IFS=, t

我也有猜测跟这个有关:

m.  Fixed a bug that caused here documents to not be displayed correctly
    when attached to commands inside compound commands.

更新

在 4.2 中可以找到另一个令人困惑的行为,该行为已在 4.3 中修复。通过执行IFS=, cat &lt;&lt;&lt; "${foo[*]}""${foo[*]}" 可以很好地扩展"111 222 333"(不受 IFS 影响),如cat 所示,即111 222 333。但是,当我们执行IFS=, read bar &lt;&lt;&lt; "${foo[*]}"; echo "$bar" 时,输出将是111,222,333,并且看起来好像"${foo[*]}" 扩展为"111,222,333"。这种不一致的行为在 Bash 4.3 中不再发生,而 Bash 4.3 的行为可能是一个修复。

【讨论】:

  • +1 cat 不使用IFS;像IFS=, read a b c 这样的东西可以工作,因为read 是一个bash 内置程序,而不是一个外部程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
  • 2014-06-25
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-27
相关资源
最近更新 更多