以下是一个简单的 shell 脚本示例:
#!/usr/bin/env bash
if [ 1 == 1 ]; then
echo "Something"
fi
当我运行这个
sh ./test.sh
我得到:
./test.sh: 4: ./test.sh: Syntax error: "fi" unexpected (expecting "then")
它似乎无法识别我在其中的“then”。有什么线索可以解释原因吗?如果这部分很重要,这是适用于 Windows 的 Ubuntu。
运行 shell 脚本通常不是问题,只是 if/else 有点问题。
答案1
这里有两个问题。首先,虽然你有一个舍邦线调用 bash,您将以 的身份执行脚本sh script.sh
。shebang 行已经为该脚本指定了解释器。因此,只需使脚本可执行即可:
chmod a+x ./test.sh
然后运行它:
./test.sh
或者,使用 bash 明确运行它:
bash ./test.sh
这将使它使用bash
而不是 来运行sh
,这是一个功能更有限的 shell,并且不理解==
。这给我们带来了第二个问题以及为什么会失败。奇怪的是,你想要eq
或=
,而不是==
。在 POSIX shell 脚本中测试数字相等性的运算符(sh
是符合 POSIX 的 shell)是,-eq
而测试的运算符是细绳平等既是事物=
,又==
不是事物。
因此,如果您希望脚本由 运行sh
,请将其更改为:
if [ 1 = 1 ]; then
echo "Something"
fi
这检查细绳 1
和细绳 1
,或者进行数值比较,使用:
if [ 1 -eq 1 ]; then
echo "Something"
fi
此外,您还有另一个问题。如果我在 后面dash
添加 ,我只能重现您遇到的特定错误。这是在 Windows 和 Linux 之间移动时的一个经典问题。虽然 Linux 使用作为行结束符,但 Windows 使用 来结束行。此字符对用户不可见,但它存在并混淆脚本。因此,您可以使用以下命令将其删除:\r
then
\n
\r\n
\r
sed -i 's/\r//' ./test.sh
以后,请使用合适的文本编辑器来编写脚本。要么是可以在 WSL 系统中运行的编辑器,要么是至少可以配置为不添加\r
到行尾的编辑器。
答案2
让我们简单一点:
sh
不在bash
Ubuntu 上(请参阅这以供参考)。[
是命令,与test
命令相同。它不支持==
算术比较。改用-eq
。这是由指定的实用程序之一POSIX 标准bash
,因此在和中都有效dash
。if [ 1 -eq 1 ]; then echo "it works!" fi
bash
有((
,称为算术扩展。这支持==
。此功能显然是从ksh
shell 借用的。$ var=25 bash -c 'if((var==5)); then echo Y;else echo "N";fi' N $ var=25 bash -c 'if((var==25)); then echo Y;else echo "N";fi' Y
尽管
dash
不支持if (())
,但在任何一个 shell 中$((
都可以工作,因为它是由POSIX 标准仅考虑两种 shell 共有的特征,我们可以做这样的事情,同时仍然用于==
比较:$ var=25 dash -c 'if [ $((var==25)) -eq 1 ];then echo Y; else echo N;fi' Y $ var=25 dash -c 'if [ $((var==5)) -eq 1 ];then echo Y; else echo N;fi' N
我们可以完全抛弃
if
语句并使用case
(注意,返回状态符合 C,而不是 shell 行为,即 true 为 1,false 为 0,而不是像 shell 中那样反过来):$ dash -c 'case $((1==1)) in 1) echo "equal";; 0) echo "not equal";;esac' equal $ dash -c 'case $((1==2)) in 1) echo "equal";; 0) echo "not equal";;esac' not equal
或者我们可以巧妙地使用算术扩展:
$ var=25 dash -c '_0(){ false;}; _1(){ true;}; if "_$((var==25))" ; then echo Y; else echo N; fi'