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}
的含义是什么?
谢谢你的帮助。
答案 0 :(得分:12)
$-
表示shell标志。
${-#*i}
表示shell标记减去*i
的首次匹配。
如果这两者不相等,那么shell被认为是交互式的(标志i
存在)。
答案 1 :(得分:11)
top answer见What does “${-#*i}” != “$-” mean? Unix & Linux上的cuonglm至POSIX documentation:
$-
是shell本身在调用时设置的当前选项标志, 或使用set
内置命令:$ echo $- himBH $ set -a $ echo $- ahimBH
"${-#*i}"
是字符串删除的语法:(来自the gettext source)$ {参数#[字]}
删除最小的前缀模式。这个词应该扩展到产生 一种模式。然后参数扩展将产生参数, 前缀的最小部分与模式匹配 删除。
如果存在,则单词不得以不带引号的“
#
”开头。$ {参数 ## [字]}
删除最大的前缀模式。这个词应该扩展为产生一个 图案。然后参数扩展将产生参数 前缀的最大部分与删除的模式匹配。
所以
${-#*i}
删除最短的字符串,直到第一个i
字符:enter code here $ echo "${-#*i}" mBH
在你的情况下,
if [ "${-#*i}" != "$-" ]
检查你的shell是不是 互动与否。
答案 2 :(得分:7)
<强> TL; DR:强>
如果当前shell是 interactive ,则条件[ "${-#*i}" != "$-" ]
将评估为逻辑 true ,在这种情况下,退出代码设置为0
,发出 true 信号,这会导致封闭的if
语句then
分支被执行。
整个问题中的条件和代码仅故意使用POSIX-compliant shell-language syntax and commands以便可移植(适用于所有POSIX- 兼容的 shell可以充当/bin/sh
)。
请注意,如果可以将bash
假设为shell,则相同的条件可以更容易地表示为
[[ $- == *i* ]]
${-#*i}
是parameter expansion,用于删除与pattern #
匹配的最短前缀(*i
)。 1}}(命名参数通常称为变量)。
$-
是special parameter,其中包含(链接和重点):
扩展为当前option标记(单字母选项名称连接成字符串),如调用时所指定的那样,设置为特殊构建在命令中,或由shell隐式地。
交互式 shell 隐式将选项标记$-
添加到i
的值;换句话说:$-
值中存在字母i
意味着手头的shell是交互式,相反,缺席 > $-
意味着shell是非交互式的。
因此,在参数展开i
中,如果${-#*i}
存在,模式*i
将仅在$-
的值内匹配,如果存在,通过删除 i
匹配的内容,返回子字符串(在本例中为后缀)*i
。
换句话说:只有在交互式 shell中,$-
不等于${-#*i}
,因为在非交互式 shell中 - 由于缺少$-
- 参数扩展具有 no 效果,并且两个操作数相等。
简而言之:代码使用它在i
中找到的shell脚本来初始化当前的shell;更具体地说:
位于目录/etc/profile.d
中的当前用户可读的脚本(名为*.sh
的文件)(/etc/profile.d
)将逐个传递给.
(dot) utility ,按字母顺序排列。点实用程序执行当前 shell中每个文件的命令,通常用于定义别名,函数和环境变量。这通常称为 sourcing 文件。
输出的处理方式不同,具体取决于当前shell是否具有交互性:
交互式 shell:输出通过(将在交互式shell中显示)。
非交互式 shell:输出被抑制(-r
是符合POSIX标准的方式,可以使stdout和stderr静音。)