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 都静音的方法)。
在 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 theset
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,反之, 缺少 ofi
意味着 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 都静音的方法)。