Shell 脚本并不是真正意义上的完整语言,它在很大程度上依赖于其他外部命令才能工作。
变量使用它们前面的符号。$
许多 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
如您所见,当应该扩展变量时使用符号,而不是在定义它时使用。那是因为 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
创建了该命令。你可以做一个man 测试,看看如何使用它。
该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
(它是命令的参数,参数以破折号开头!)。它还解释了为什么在[
and周围需要空格]
。这些是实际的 Unix 命令,Unix 命令周围必须有空格,以便 shell 可以处理它们。
Another issue is: Why does the shell have two different sets of tests for strings and numbers? That's because strings may contain nothing but digits, but are not really numeric. For example, if you do inventory, you might have a part number 001
and 01
. Numerically, they're equal, but as strings, they're two different strings. There is no way for the shell script to know. Instead, you must let the shell script know if it's a numeric comparison or a string comparison.
Perl has similar issues since you don't declare variables as numeric or non-numeric:
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
You can try a few other things:
$ echo "*" # Echos the asterisk
$ echo * # No quotes: Prints all files in current directory
Notice again the shell expands the *
before executing the echo command. This is the main difference between a shell script and a typical programming language. The shell first does expansion (fill in environment variables, glob substitution, and run sub-commands) before it actually executes the command.
The set -xv
will show you what command is being executed, and how the shell expands the command before executing. Doing set +xv
will shut that off. Play around with that, and you'll soon understand the shell a bit better.