【问题标题】:unset IFS - unexpected behaviour未设置 IFS - 意外行为
【发布时间】:2017-01-25 12:42:57
【问题描述】:

我认为人们普遍认为unset IFS 将 IFS 恢复为其默认值。
我找不到以下代码的原因

echo -n "_${IFS}_" | xxd
IFS=':'
echo -n "_${IFS}_" | xxd
unset IFS
echo -n "_${IFS}_" | xxd
echo "${IFS-IFS is unset}"

返回这个

0000000: 5f20 090a 5f                             _ .._
0000000: 5f3a 5f                                  _:_
0000000: 5f5f                                     __
IFS is unset

在我的 Ubuntu 和 Android 中。
如您所见,IFS 实际上是未设置的。
提前致谢

【问题讨论】:

  • @anubhava 正如@tripleee 的链接所解释的那样,IFS 未恢复为默认值$' \t\n' 是出乎意料的。你们真的看过我的问题吗?
  • unset IFS 确实会取消设置 IFS。它不会设置为$' \t\n'。虽然空的IFS 也表现得像将它设置为$' \t\n'
  • 感谢@anubhava,现在我明白了。
  • @anubhava 这仅在某些情况下是正确的。在其他情况下,如果您 unset IFS 可能会导致难以找到错误,则这是错误的。

标签: linux bash sh


【解决方案1】:

我也看到有人发帖说,如果您取消设置 IFS,则会将其恢复为默认值。这里的其他答案有助于澄清故事......

在实际使用的基础上,我想补充一点,我确实没有在 Ubuntu 和 Droid 上观察到与操作报告相同的情况。我在 Ubuntu 18 中针对/bin/sh 进行了测试,它按预期工作(就像它被 恢复 到空白字符一样)。但是,在 Yocto(另一个 Linux 发行版)上,使用 /bin/sh 等同于 BusyBox(就像您在 Droid 上找到的那样),unset IFS 导致它的行为就像它被设置为 NULL,即参数之间没有分隔符它们在函数等中收到时。

为了解决这个问题,我定义了一个“常量”DEFAULT_IFS=$' \t\n' 并将 IFS 分配给它,而不是使用 unset。这种方法对我来说适用于不同的环境。

【讨论】:

    【解决方案2】:

    引用 POSIX / http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05:

    如果 IFS 的值为 ,或者如果未设置,...

    这并不意味着取消设置 IFS 会自动将其重置为 " \t\n"。这只是意味着如果您取消设置 IFS,则分词就像将 IFS 设置为 " \t\n" 一样。

    【讨论】:

      【解决方案3】:

      我认为人们普遍认为取消设置 IFS 会将 IFS 恢复为其默认值。

      这是完全错误的,任何文档中都没有提到这一点!


      让我们在the reference manual 中搜索IFS,看看我们能学到什么:

      3.4.2 Special Parameters

      * ($*) 展开为位置参数,从一开始。当扩展不在双引号内时,每个位置参数都会扩展为一个单独的单词。在执行它的上下文中,这些词会受到进一步的分词和路径名扩展。当扩展出现在双引号内时,它会扩展为一个单词,每个参数的值由IFS 特殊变量的第一个字符分隔。即$* 等价于$1c$2c…,其中cIFS variable 值的第一个字符。 如果IFS 未设置,则参数以空格分隔。 如果IFS 为空,则将参数连接起来,不插入分隔符。

      试试看:

      $ set -- one two three
      $ IFS=hello
      $ echo "$*"
      onehtwohthree
      $ unset IFS
      $ echo "$*"
      one two three
      $
      

      类似数组的扩展也会发生类似的扩展:"${array[*]}""${!prefix*}"

      3.5.7 Word Splitting

      shell 将$IFS 的每个字符视为分隔符,并使用这些字符作为字段终止符将其他扩展的结果拆分为单词。 如果未设置IFS,或者它的值正好是默认的<space><tab><newline>那么<space><tab><newline>的序列在结果的开头和结尾前面的扩展将被忽略,任何不在开头或结尾的IFS 字符序列都用于分隔单词。

      也许混淆来自粗体部分。

      read 内置函数的参考也参考了这一节,所以我们不会在那里学到任何新东西。 IFS 的其他提及不会给图片带来任何新内容。


      结论。

      不,取消设置 IFS不会将其重置为默认值。手册中的任何地方都没有提到这一点。令人困惑的原因是手册指定,对于分词(以及类似数组的参数的* 形式),未设置的IFS 产生与IFS 的默认值相同的行为。

      【讨论】:

        猜你喜欢
        • 2016-09-29
        • 1970-01-01
        • 1970-01-01
        • 2021-11-29
        • 1970-01-01
        • 1970-01-01
        • 2017-07-31
        • 1970-01-01
        • 2017-06-22
        相关资源
        最近更新 更多