【问题标题】:What does the ${-#*i} mean in shell script?${-#*i} 在 shell 脚本中是什么意思?
【发布时间】:2017-06-22 20:22:37
【问题描述】:

在 CentOS 6 上的文件 /etc/profile 中有一个 for 循环:

for i in /etc/profile.d/*.sh ; do
    if [ -r "$i" ]; then
        if [ "${-#*i}" != "$-" ]; then
            . "$i"
        else
            . "$i" >/dev/null 2>&1
        fi
    fi
done

上述 for 循环中的${-#*i} 是什么意思?
感谢您的帮助。

【问题讨论】:

  • 当我读到标题时,我以为你在那儿删掉了一个 ${-#*i}ng 坏词......

标签: linux shell centos6


【解决方案1】:

tl;博士:

如果当前 shell 是 交互式,则条件 [ "${-#*i}" != "$-" ] 评估为逻辑 true,在这种情况下,退出代码设置为 @987654328 @,表示 true,这会导致执行封闭的 if 语句的 then 分支。

问题中的条件和代码作为一个整体故意仅使用 POSIX-compliant shell-language syntax and commands 以便可移植(与所有可能起作用的 POSIX-兼容 shell 一起使用如/bin/sh)。

请注意,如果bash 可以假定为外壳,例如,相同的条件可以更易读地表示为
[[ $- == *i* ]]


说明

  • ${-#*i} 是一个 parameter expansion,它从命名参数 $- 的值中删除与 pattern *i 匹配的最短前缀 (#)(命名参数通常称为变量)。

  • $-special parameter,其中(添加了链接和重点):

    扩展为 当前option 标志单字母选项名称连接成一个字符串),如调用时指定的,由 set 特殊内置命令, 或由 shell 隐含。

  • 一个交互式 shell隐式将选项标志i添加到$-的值;换句话说:$- 的值中存在字母 i 意味着手头的 shell 是交互式的,相反,@987654343 的 不存在 @ 表示 shell 非交互式

  • 1234563 /em> *i 匹配的内容,返回$-子字符串(在本例中为后缀)。
    换句话说:只有在 interactive shell 中,${-#*i} not 才等于 $-,因为在 noninteractive shell 中 - 由于不存在i - 参数展开作用,两个操作数相等。

问题中的代码的作用作为一个整体

简而言之:代码使用在/etc/profile.d 中找到的shell 脚本来初始化当前shell;更具体地说:

  • 当前用户 (-r) 可以读取的目录 /etc/profile.d 中的脚本(名为 *.sh 的文件)按字母顺序一一传递给 . (dot) utility。 dot 实用程序从 current shell 中的每个文件执行命令,通常用于定义别名、函数和环境变量。这通常称为采购文件。

  • 输出每个源脚本产生的处理方式不同,具体取决于当前 shell 是否是交互式的:

    • 交互式 shell:输出通过(将在交互式 shell 中可见)。

    • noninteractive shell:输出被抑制>/dev/null 2>&1 是符合 POSIX 标准的方式来使 stdout 和 stderr 都静音)。

      李>

【讨论】:

    【解决方案2】:

    请参阅Unix & Linux 上的top answerWhat does “${-#*i}” != “$-” mean? cuonglm

    $- 是 shell 本身在调用时设置的当前选项标志, 或使用set 内置命令:

    $ echo $-
    himBH
    $ set -a
    $ echo $-
    ahimBH
    

    "${-#*i}" 是删除字符串的语法:(来自POSIX documentation

    ${参数#[单词]}

    删除最小前缀模式。该词应扩展为产生 一种模式。然后参数扩展将导致参数, 前缀的最小部分与模式匹配 已删除。

    如果存在,单词不应以未引用的“#”开头。

    ${参数##[单词]}

    删除最大前缀模式。该词应扩展为产生一个 图案。然后参数扩展将导致参数,与 与删除的模式匹配的前缀的最大部分。

    所以${-#*i} 删除最短的字符串直到第一个i 字符:

    enter code here
    $ echo "${-#*i}"
    mBH
    

    在您的情况下,if [ "${-#*i}" != "$-" ] 检查您的外壳是否是 互动与否。

    【讨论】:

    • 我已经编辑了您的答案,以正确引用和归属原作者。在帮助中心查看Referencing;建议是“仅引用相关部分”,而不是完整答案。
    【解决方案3】:

    $- 表示 shell 标志。

    ${-#*i} 表示 shell 标志减去 *i 的第一个匹配项。

    如果这两个不相等,则认为 shell 是交互式的(存在标志 i)。

    【讨论】:

      猜你喜欢
      • 2012-04-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      • 2017-04-17
      • 2013-12-03
      • 2013-04-08
      • 1970-01-01
      相关资源
      最近更新 更多