Bash基础知识

在上一篇文章《不过时的技术-Bash脚本》中,我们简单介绍了Bash脚本,并且学会如何编写、运行一个Bash脚本。这篇文章我们将目光转向Bash脚本的一些基础知识:

  1. 如何定义、使用变量
  2. export和source
  3. 特殊字符及转义
  4. 脚本参数
  5. 命令替换
  6. 字符串验证
  7. Here文档

变量

有三种方式定义变量:

  1. 在命令行或脚本中直接显式定义
    COLOR=red
    千万不要像其他编程语言一样在变量和=之间加空格!!!
  2. 使用read命令从标准输入给变量赋值
    read COLOR
  3. 第三种变量比较特殊,由参数直接传入:$0$1$2……其中$0为脚本名,$1是第一个参数,以此类推。

在变量名前加$符引用变量,比如$COLOR。下面这段脚本让用户输入进程名,保存到一个变量里,然后查找相关进程并杀掉。

#!/bin/sh

# Ask what to stop using the kill command and then kill it
echo which process do you want to kill?
read TOKILL

kill $(ps aux | grep $TOKILL | grep -v grep | awk '{print $2}')

这个脚本的最后一句看起来有点复杂,用到了命令替换、管道、awk等知识。如果你是那种不怕麻烦的人,可在命令行中一点一点去执行,看看发生了什么:比如ps aux返回当前进程,ps aux | grep http在当前进程中找出http相关进程,以此类推……事实上这是编写脚本时常用的方法,先在命令行中一部分一部分实验,成功后再组织成一段脚本。

如果执行脚本时出错怎么办?比如上面这段脚本运行第二次时,如果输入的值一样,就会报错。此时运行bash -x tokill.sh可以打印出详细的诊断信息:

foo:bin muxi$ bash -x tokill.sh 
+ echo which process do you want to 'kill?'
which process do you want to kill?
+ read TOKILL
http
++ ps aux
++ grep -v grep
++ grep http
++ awk '{print $2}'
+ kill
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]

相信你已经看出了问题所在,最后一步kill进程时传入的参数不对(为空)。这点不难想象,因为我们已经在上一次运行时杀掉所有相关进程了。

需要注意的是变量只在定义它的脚本中起效,如果在当前脚本中进入子脚本,那么该变量在子脚本中就不存在了。这点可以在命令行中得到验证:

foo:bin muxi$ COLOR=red
foo:bin muxi$ echo $COLOR
red
foo:bin muxi$ bash
bash-3.2$ echo $COLOR

bash-3.2$ COLOR=green
bash-3.2$ echo $COLOR
green
bash-3.2$ exit
exit
foo:bin muxi$ echo $COLOR
red

细心的读者可能会注意到,定义变量时我一直用的大写,这是一个好的编程习惯,人家一看就知道这是个变量。

export 和 source

如果想使用父脚本中定义的变量该怎么办?答案是使用export将变量导入子脚本:

foo:bin muxi$ export COLOR=red
foo:bin muxi$ echo $COLOR
red
foo:bin muxi$ bash
bash-3.2$ echo $COLOR
red

source更厉害,它能将一个脚本中的所有内容导入到另外一个脚本中。

#!/bin/sh

. ./slave.sh

echo the value of variable '$COLOR' is $COLOR

exit 0
#!/bin/sh

COLOR=yellow

source的厉害之处在于它能将变的东西和不变的东西分离开,听着是不是很熟悉?这是计算机世界里一个基本的原则之一。以后大家会经常在脚本中看到exportsource

特殊字符和转义

在Shell脚本中,很多字符有特殊的含义:~代表当前用户主目录, #注释等,更多内容可参考特殊字符列表。比如下面这段脚本,你觉得输出会是什么?

echo 2 * 3 > 5

上面的脚本什么也没输出,它将一段文本重定向到文件5中。为了输出2 * 3 > 5,需要这样:echo '2 * 3 > 5'

脚本参数

执行脚本时可传入参数,在脚本中使用$0, $1, $2……${10}, ${11}……引用参数,其中$0代表脚本名。还有三个特殊变量:$#表示传入参数个数,$@返回所有参数列表,$*将所有参数以一个字符串的形式返回。下面这段程序用来遍历参数列表,你能猜出为什么"$@"要加双引号吗?

for i in "$@"
do
    echo $i
done

命令替换

编写脚本时,经常一个命令需要使用另一个命令执行完成后的结果,此时就用到了命令替换,比如ls -l $(which passwd)列出了passwd命令的文件属性。

字符串验证

test -z $1 && exit 1 #如果第一个参数为空,返回状态1退出
[[ $1=='[a-z]*' ]] || echo $1 does not start with a letter
恐怖的空格!!!$1之前必须有空格,之后必须没空格!!!

Here文档

wall <
#!/bin/bash
# example of a scripted FTP session

lftp localhost <

你可能感兴趣的:(Bash基础知识)