Shell 脚本并不是真正意义上的完整语言,它在很大程度上依赖于其他外部命令才能工作。
变量使用sigil,即它们前面的$。许多 shell 脚本语言使用变量符号来帮助区分字符串和变量。
例如:
foo=foo_value
echo foo foo $foo foo
将打印:
foo foo foo_value foo
请注意,字符串的 echo 语句不需要引号。 Windows Batch shell 非常相似:
set foo = foo_value
echo foo foo %foo% foo
如您所见,sigil 是在应该扩展变量时使用的,而不是在您定义它时使用的。那是因为 Unix shell 是智能 shell。他们甚至在执行命令行之前就对它进行了修改。 shell 将替换环境变量之前执行:
foo=bar
$foo="whose value is this" # Note the dollar sign!
echo The value of foo is $foo
echo The value of bar is $bar
这将打印出来:
The value of foo is foo
The value of bar is whose value is this
如果您使用set -xv 命令,您会看到$foo="whose value is this" 在执行之前扩展为bar=whose value is this"。
在像 KornShell 和 Bash 这样的 Bourne 风格的 shell 中,if 语句并不是你想象的那样。 if 命令执行语句,如果该命令返回零值,将选择 if 子句。例如:
cat "foo" > my_file # Create a one line file with the string foo in it.
if grep -q "foo" my_file # grep command will return a zero exit code if it finds foo
then
echo "The string 'foo' is in file my_file"
fi
请注意,if 子句 不是布尔语句。这是一个实际执行的命令。
在 Unix 开发的早期,test 命令被创建。您可以进行人工测试,看看如何使用它。
test 命令允许您这样做:
foo=3
bar=3
if test foo -eq bar
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
如果你这样做:
$ ls -li /bin/test /bin/[
您将看到名为[ 的命令实际上存在,并且是test 命令的硬链接。这是为了让if 语句看起来更像是您将在常规编程语言中看到的 if 语句:
foo=3
bar=3
if [ foo -eq bar ]
then
echo "foo and bar are equal"
else
echo "foo and bar are not equal"
fi
它与上面的脚本完全相同,但使用[ 而不是test。
这解释了为什么在许多测试中需要 破折号(它是 test 命令的参数,参数以破折号开头!)。它还解释了为什么在[ 和] 周围需要空格。这些是实际的 Unix 命令,Unix 命令周围必须有空格,以便 shell 可以处理它们。
另一个问题是:为什么 shell 对字符串和数字有两组不同的测试?那是因为字符串可能只包含数字,但不是真正的数字。例如,如果您进行库存,您可能有一个零件号001 和01。在数值上,它们是相等的,但作为字符串,它们是两个不同的字符串。 shell脚本无法知道。相反,您必须让 shell 脚本知道它是数字比较还是字符串比较。
Perl 也有类似的问题,因为您没有将变量声明为数字或非数字:
Shell Script Perl
Boolean Operator Numeric String Numeric String
=================== ======= ====== ======= ======
Equals -eq = == eq
Not Equals -ne != != ne
Greater Than -gt > > gt
Less Than -lt < < lt
Greater or Equals -ge >= >= ge
Less Than or Equals -le <= <= le
您可以尝试其他一些方法:
$ echo "*" # Echos the asterisk
$ echo * # No quotes: Prints all files in current directory
在执行 echo 命令之前再次注意 shell 扩展 *。这是 shell 脚本和典型编程语言之间的主要区别。 Shell 在实际执行命令之前首先进行扩展(填充环境变量、glob 替换和运行子命令)。
set -xv 将显示正在执行的命令,以及 shell 在执行前如何扩展命令。执行set +xv 将关闭它。尝试一下,您很快就会更好地理解 shell。