2

在我的 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 语句来重定向输出?谢谢!

4

4 回答 4

8

$-是一个变量,它存储由 shell 设置的当前选项

${-#*i}正在使用子字符串删除*i从变量的开头删除与模式的最短匹配。因此,如果$-有值abcifOO,那么${-#*i}将是fOO(您可以在此处阅读有关 bash 子字符串的更多信息。)

这意味着测试

[ "${-#*i}" != "$-" ]

如果变量$-包含 option i,则为真,这意味着交互模式已打开。

/dev/null总之,这意味着只有在交互模式下才会重定向输出。

于 2013-10-09T04:24:45.577 回答
4

它正在检查外壳是否是交互式的。当前 shell 的选项在$-,如果删除后面的任何内容会i产生不同的结果,这意味着它i在标志中。

不过,这将更具可读性和惯用性:

case $- in *i* ) ... ;; esac

此外,最好在循环外进行一次检查。

于 2013-10-09T04:25:00.270 回答
2

是什么$-意思?

从手册:

-

(一个连字符。)扩展为调用时指定的当前选项标志,由 set 内置命令,或由 shell 本身设置的那些(例如-i选项)。

当您以bash 交互方式运行时,$-可能会扩展为:

himBH

当您执行脚本时,$-不会有i(除了上面的一些其他标志)。

是什么${-#*i}意思?

${-#*i}导致*i从扩展的开头的最短匹配$-被删除。(请参阅壳参数扩展。)

简而言之,if示例中的内部条件意味着在交互模式下执行以下操作:

. "$i" >/dev/null 2>&1

在非交互模式下,以下内容:

. "$i"
于 2013-10-09T04:24:24.600 回答
1

只是为了添加更多关于 $- 的细节。如果您尝试在终端中输入

[root@zee ~]# echo $-
himBH

这些似乎是外壳“设置”值

片段来自info bash --index-search=set

 '-h'

查找并记住(散列)命令,因为它们被查找执行。默认情况下启用此选项。

 '-m'

作业控制已启用 (*note Job Control::)。

 '-B'

shell 将执行大括号扩展 (*note Brace Expansion::)。此选项默认开启。

'-H'

使能够 '!' 样式历史替换 (*note History Interaction::)。对于交互式 shell,此选项默认启用。

使用+' rather than-' 会关闭这些选项。这些选项也可以在调用 shell 时使用。

于 2013-10-10T20:25:50.507 回答