Command Files
可以把任何命令行直接输入的命令放到一个文件中,给文件赋予可执行权限后就能直接运行,这就是 shell 脚本。
Commnets
shell 使用 # 注释。
Variables
和其他编程语言一样,shell 也有变量。使用 variable=value 的形式定义变量。
注意:
- 等号两边不能有空格
- shell 没有数据类型的概念,统一当作字符串处理
count=1这里的 1 会当作字符
因为 shell 是一种解释型的语言,可以直接在终端上给变量赋值。
显示变量的值
使用 echo 显示变量的值 echo $var,对 shell 来说 当 $ 符号后跟几个字符时,$ 是有特殊含义的,shell 在执行脚本时会进行 variable substitution。
变量可以用在任何命令和任何地方,并且在执行之前会被 shell 替换。
ls $my_bin,cd $my_bin,number=99 echo There are $number cats。
1 | command=wc |
shell 先进行变量替换再执行命令。
变量可以赋值给其他变量
1 | val1=10 |
记住无论什么时候想使用存储在变量中的值都需要使用 $ 符号。
Undefined Variables Have the NULL Value
打印未定义的变量会发生什么?会报错吗?echo $nosuch 不会报错,但是 shell 打印出东西了吗? echo :$nosuch:,对于未指定值的变量,没有字符被 shell 替换。
A variable that contains no value is said to be undefined and contain the null value.
当 shell 进行变量名替换时,如果发现有些变量是 null,那么直接从命令行移除这个变量。
wc $nosuch -l $nosuch $nosuch names shell 扫描命令行,使用 null 替换 $nosuch,当扫描结束后,命令变成 wc -l names,这就是为什么这个命令能工作的原因。
但是有时就想使用空值初始化变量怎么办?dataflag= 更好的做法是 dataflag="" or dataflag=''。后两个和第一个效果一样,但是更实用。
注意 dataflag=' ' 和前面的是不相同的,dataflag 此时保存的是一个空格。
Filename Subsitution and Variables
有个 puzzle,x=* x 是什么,shell 会把字符 * 存到变量 x 中,还是把当前文件夹下所有的文件名存到 x 里面呢?答案是后者。
1 | ls |
从这个例子中可以学到很多,是在执行 x=* 的时候保存了文件名还是执行 echo $x 时 shell 执行替换呢?
shell 在定义变量时并不会执行 filename subsitution,因此 x=*,只会把 * 赋值给 x,在变量替换后执行 echo 前会进行文件名替换。
执行顺序:
- shell 扫描命令行,使用
*替换变量 - shell 再次扫描命令行,遇到
*,然后使用当前目录下所有文件名替换* - shell 开始执行
echo,把文件名当参数传给echo

evaluation 的顺序是非常重要的,首先进行变量替换,再进行文件名替换,然后把命令行解析为参数。
The ${variable} Construct
假设有个变量保存了文件名,现在希望重命名文件,新的文件名加上 x。
mv $fn $fnx 这样做显然不行,shell 会把 $fnx 当作变量替换,可以使用构造器。
mv $fn ${fn}x 这样就消除了任何歧义。
对于这种形式的变量构造器,还有很多函数可以使用,比如提取子集,如果变量未定义给定值等操作。
Built-in Interger Arithmetic
POSIX 标准 shell 提供了一种叫做 arithmetic expansion 机制来操作变量上的整数运算。有些老的 shell 不一定支持。
arithmetic expansion 的格式是 $((expression)),expression 是使用 shell 变量和操作符的表达式。 有效的变量是只包含数字的变量,前后空格是允许的,有效的操作符是从 C 语言借鉴来的。
$(()) Operators
有效的操作符号很多,包括基本的 6 个操作符:+、-、*、/、% 和 **,还包括 +=、-=、*=、/=、i++、i-- 等等。
还可以基于不同进制的数字进行进制转换,比如八进制的 100 echo $((8#100)),二进制 echo $(( 2#101010101010101010 ))。
计算表达式会在命令行被替换,比如 echo $((i+1)),对 shell 变量 i 中的值加一,并打印结果,注意这里的 i 不需要用 $ 来引用,因为 shell 知道只有 operators、numbers 和 变量 才能出现在 arithmetic expansion 中。
如果变量没有值或者是空,那么会使用 0 替代,echo $((a=a+1)),a 未定义,会当作 0处理,结果 a 中保存了 1。
注意赋值符号也是有效的 operator,所以 a 的值是 1,同样可以使用括号来保证计算的优先级。
echo $((i=(i+10)*j)),同样可以直接赋值,i=$((i * 5)) 注意计算表达式中的空格是无所谓的,但是 shell 赋值必须没有空格。
$((i++)) i 的值是会变的,同样可以使用逻辑运算,result=$((i>=10 && i<=100)),真是 1 ,假是 0。