如果shell脚本中的/ Else在Ubuntu for Windows中引发错误
这是一个简单的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")
它似乎没有认出我在那里的’那么’。 任何线索为什么? 这是部分重要的Ubuntu for Windows。
一般运行shell脚本不是问题,它似乎与if / else斗争。
这里有两个问题。 首先,当你有一个调用bash的shebang行时 ,你正在以sh script.sh
forms执行脚本。 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
另外,你还有另外一个问题。 如果我在那then
添加\r
,我只能重现你在dash
获得的特定错误。 在Windows和Linux之间移动时,这是一个经典问题。 虽然Linux使用\n
作为行结束字符,但Windows以\r\n
结束其行。 这个\r
字符对用户不可见,但它存在并且会混淆脚本。 所以,您可以删除它:
sed -i 's/\r//' ./test.sh
在将来,使用适当的文本编辑器编写脚本。 在WSL系统中工作的那个,或者至少可以配置为不将\r
添加到其行的末尾的那个。
让我们保持简单:
-
sh
不是Ubuntu上的bash
(请参阅此参考)。 -
[
是一个命令,与test
命令相同。 它不支持==
进行算术比较。 请改用-eq
。 这是POSIX标准指定的实用程序之一,因此可以在bash
和dash
。if [ 1 -eq 1 ]; then echo "it works!" fi
-
bash
有((
这叫做算术扩展。这支持==
。这个function显然是从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共有的function,我们可以做这样的事情,同时仍然使用==
进行比较:$ 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
-
或者我们可以使用算术扩展偷偷摸摸(ab):
$ var=25 dash -c '_0(){ false;}; _1(){ true;}; if "_$((var==25))" ; then echo Y; else echo N; fi'