shell 脚本中的 ${-#*i} 是什么意思?

What does the ${-#*i} mean in shell script?

在 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}是什么意思?
感谢您的帮助。

$- 表示 shell 个标志。

${-#*i} 表示 shell 标志减去 *i.

的第一个匹配项

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

参见top answer to What does “${-#*i}” != “$-” mean? on Unix & Linux by cuonglm

$- is current option flags set by the shell itself, on invocation, or using the set builtin command:

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

"${-#*i}" is syntax for string removal: (from POSIX documentation)

${parameter#[word]}

Remove Smallest Prefix Pattern. The word shall be expanded to produce a pattern. The parameter expansion shall then result in parameter, with the smallest portion of the prefix matched by the pattern deleted.

If present, word shall not begin with an unquoted '#'.

${parameter##[word]}

Remove Largest Prefix Pattern. The word shall be expanded to produce a pattern. The parameter expansion shall then result in parameter, with the largest portion of the prefix matched by the pattern deleted.

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

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

对于您的情况,if [ "${-#*i}" != "$-" ] 检查您的 shell 是否 互动与否。

tl;博士:

如果当前 shell 是 interactive,则条件 [ "${-#*i}" != "$-" ] 计算结果为逻辑 true ,在这种情况下,退出代码设置为 0,发出信号 true,这会导致封闭 if 语句的 then 分支待执行。

问题中的条件和代码作为一个整体有意仅使用 POSIX-compliant shell-language syntax and commands 以便可移植(与所有 POSIX-compatible shells 可以充当 /bin/sh).

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


说明

  • ${-#*i} 是来自命名参数 $- 值的 parameter expansion that removes the shortest prefix (#) that matches pattern *i(命名参数通常称为 变量).

  • $- 是一个 special parameter,其中(link 并强调):

    expands to the current option flags (the single-letter option names concatenated into a string) as specified on invocation, by the set special built-in command, or implicitly by the shell.

  • 交互式shell隐式添加选项标志i$-的值;换句话说:在 $- 的值中出现字母 i 意味着手头的 shell 是 interactive,反之, 缺少 of i 意味着 shell 是 noninteractive.

  • 因此,在参数扩展 ${-#*i} 中,如果存在 i,则模式 *i 将仅在 $- 的值内匹配,并且, 如果是这样, 凭借 removing what *i matched, return a substring (suffix, in this case) $-.
    换句话说:只有在 interactive shell 中 ${-#*i} not 等于 $-,因为在noninteractive shell - 由于缺少 i - 参数扩展具有 no 效果,两个操作数是等于.


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

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

  • 位于目录 /etc/profile.d 中且当前用户 (-r) 可读的脚本(名为 *.sh 的文件)被传递给 [=46= 】 一个接一个,不分先后。 dot 实用程序执行 current shell 中每个文件的命令,通常用于定义别名、函数和环境变量。这通常称为 采购 文件。

  • 由每个源脚本产生的输出 根据当前 shell 是否是交互式的被不同地处理:

    • 交互 shell:输出通过(将在交互shell).

    • 非交互 shell:输出被抑制>/dev/null 2>&1是POSIX-compliant 使 stdout 和 stderr 都静音的方法)。