在我的Oracle Linux框中,我发现/etc/profile
中的一块脚本很难弄明白:
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
我的问题是if语句${-#*i}
和$-
中的变量。
那是什么意思?为什么要添加else语句来重定向输出?
谢谢!
答案 0 :(得分:8)
$-
是variable which stores the current options set by the shell。
${-#*i}
正在使用子字符串删除来从变量的开头删除与模式*i
的最短匹配。因此,如果$-
的值为abcifOO
,那么${-#*i}
将为fOO
。 (You can read more about bash substrings here.)
这意味着测试
[ "${-#*i}" != "$-" ]
如果变量$-
包含选项i
,则将为true,这意味着interactive mode已启用。
这一切意味着如果您处于交互模式,输出将仅重定向到/dev/null
。
答案 1 :(得分:4)
检查shell是否是交互式的。当前shell的选项位于$-
中,如果删除任何后跟i
的内容会产生不同的结果,则表示i
属于这些标记。
但这会更具可读性和惯用性:
case $- in *i* ) ... ;; esac
此外,最好在循环外进行一次检查。
答案 2 :(得分:2)
$-
是什么意思?
从手册:
-
(连字符。)扩展到调用时指定的当前选项标志,set builtin命令或shell设置的那些标志。 本身(例如
-i
选项)。
当您以交互方式运行bash
时,$-
可能会出现以下情况:
himBH
当您执行脚本时,$-
不会有i
(除了上面的其他标志)。
${-#*i}
是什么意思?
说${-#*i}
导致*i
的最短匹配从$-
的扩展开始被删除。 (请参阅Shell Parameter Expansion。)
简而言之,示例中的内部if
条件意味着在交互模式下执行以下操作:
. "$i" >/dev/null 2>&1
并且在非交互模式下,以下内容:
. "$i"
答案 3 :(得分:1)
只是添加一些关于$的更多细节。如果您尝试输入终端
[root@zee ~]# echo $-
himBH
那些似乎是shell'set'值
来自info bash --index-search=set
'-h'
在查找时查找并记住(哈希)命令 执行。默认情况下启用此选项。
'-m'
启用作业控制(* note Job Control ::)。
'-B'
shell将执行大括号扩展(* note Brace 扩张::)。默认情况下,此选项处于启用状态。
'-H'
启用'!'风格历史替代(*注释历史 相互作用::)。默认情况下,此选项处于启用状态 壳。
使用+' rather than
- '会导致关闭这些选项。
这些选项也可以在调用shell时使用。