我对 bash 的语法还不太熟悉,我的 '.bash_aliases' 文件中有一段代码。它要么获取一个整数作为参数,要么获取字母 'c',当它获取一个整数时,它会将该整数放入环境变量中,Web 服务器可以将其用作端口。当它获取字母 'c' 作为输入时,它会清除该变量。
当我尝试使用整数运行命令时出现错误
main@linuxWSL:~$ serverp 2000
-bash: [: missing `]'
2000: command not found
当我用字母“c”尝试时,我得到了
main@linuxWSL:~$ serverp c
-bash: [: missing `]'
c: command not found
这是我的 bash 代码:
serverp () {
if [ "$1" = "clear" || "$1" = "c" ]
then
unset PORT
echo -e "\e$CLEAR$GREEN""mWebServer port has been reset!""$CLEAN"
return 0
fi
export PORT="$1"
}
有人能帮帮我吗?谢谢!
答案1
[
不是 Bash 中的关键字,它不会使 shell 解析器以不同的方式解释其余命令行。[
是一个类似cat
或的命令echo
。[
(类似echo
)是 Bash 中的内置命令,但这仅意味着它可以在不产生额外进程的情况下运行,它仍然表现得像一个命令。
需要明确的是:[ … ]
不是语法的一部分if … then …
。if
只是测试某些代码的退出状态:if true; then …
有效,if sleep 5; then …
有效,同样if [ … ]; then …
有效(如果该[ … ]
部分本身是一个有效命令)。
[
您的系统中可能有可执行文件。尝试type -a [
。与 进行比较type -a [[
。与 相对[
,[[
是 Bash 中的一个关键字,它确实使解析器特殊处理[[
和之间的内容]]
。
[
不是关键字。正确的写法是,只有最后一个参数[ … ]
是命令。需要作为最后一个参数,否则它将无法工作。这只是为了使它作为一个块突出,就好像它是某种特殊语法一样;但它不是一种特殊语法。]
[
]
[ … ]
[ "$1" = "clear" || "$1" = "c" ]
shell 会将你的命令解释为[ "$1" = "clear"
并与"$1" = "c" ]
连接||
。因此有两个命令。第一个命令是[ "$1" = "clear"
,[
被执行,但它没有获得]
最后一个参数,它会报错并以非零退出状态退出。由于非零状态和||
,shell 会尝试运行第二个命令,该命令以扩展为 开头"$1"
。这样,你的脚本的第一个参数将被解释为要运行的可执行文件。
[ … || … ]
像这样修复你:
[ "$1" = "clear" ] || [ "$1" = "c" ]
此代码片段包含两个有效的 [
命令。它应该会执行您想要的操作。
注意[[ "$1" = "clear" || "$1" = "c" ]]
是一段可运行的代码,而[ "$1" = "clear" || "$1" = "c" ]
不是。这是因为[[
不是命令。它是一个关键字,它使 shell 解析器将所有内容]]
特殊处理;这包括||
。还有其他[[
和之间的差异[
,不要盲目地互换它们。
[
Bash 内置命令-o
支持或者(-a
以及和),因此下面这个也可以:
[ "$1" = "clear" -o "$1" = "c" ]
您的代码中,将||
(特定于 shell) 替换为-o
(不特定于 shell)。-o
但您应该避免这样做。从本文:
二进制
-a
和-o
[…] 是 POSIX 标准的 XSI 扩展。在 POSIX-2008 中,它们都被标记为过时。它们不应在新代码中使用。[ A = B -a C = D ]
(or ) 的一个实际问题是 POSIX 不指定带有超过 4 个参数的or命令-o
的结果。它可能在大多数 shell 中都有效,但您不能指望它。如果您必须为 POSIX shell 编写,那么您应该使用由运算符分隔的两个or命令。test
[
test
[
&&
请注意,本文详细阐述了-a
,因此“&&
改为使用运算符”。在您的例子中,分别是-o
和||
。用运算符分隔的两个测试||
正是我们的解决方案。
答案2
它是if [ "$1" = "clear" ] || [ "$1" = "c" ]
。