0%

Shell脚本和变量

Command Files

可以把任何命令行直接输入的命令放到一个文件中,给文件赋予可执行权限后就能直接运行,这就是 shell 脚本。

Commnets

shell 使用 # 注释。

Variables

和其他编程语言一样,shell 也有变量。使用 variable=value 的形式定义变量。

注意:

  • 等号两边不能有空格
  • shell 没有数据类型的概念,统一当作字符串处理 count=1 这里的 1 会当作字符

因为 shell 是一种解释型的语言,可以直接在终端上给变量赋值。

显示变量的值

使用 echo 显示变量的值 echo $var,对 shell 来说 当 $ 符号后跟几个字符时,$ 是有特殊含义的,shell 在执行脚本时会进行 variable substitution

变量可以用在任何命令和任何地方,并且在执行之前会被 shell 替换。

ls $my_bincd $my_binnumber=99 echo There are $number cats

1
2
3
4
command=wc
option=-l
file=names
$command $option $file

shell 先进行变量替换再执行命令。

变量可以赋值给其他变量

1
2
3
4
5
6
val1=10
val2=val1
echo $val2

# 跟想的不一样?
val2=$val1 # this is better

记住无论什么时候想使用存储在变量中的值都需要使用 $ 符号。

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
2
3
4
5
6
$ ls 
f1.txt
f2.txt
$ x=*
$ echo $x
f1.txt f2.txt

从这个例子中可以学到很多,是在执行 x=* 的时候保存了文件名还是执行 echo $x 时 shell 执行替换呢?

shell 在定义变量时并不会执行 filename subsitution,因此 x=*,只会把 * 赋值给 x,在变量替换后执行 echo 前会进行文件名替换。

执行顺序:

  1. shell 扫描命令行,使用 * 替换变量
  2. shell 再次扫描命令行,遇到 *,然后使用当前目录下所有文件名替换 *
  3. shell 开始执行 echo,把文件名当参数传给 echo

shell

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。