bash脚本基础
1. 简介
深入了解一些代码之后,发现bash老是阻挡自己的脚步,尤其是一些项目跑在Linux环境下,Coders便会选择写一个shell脚本,想自己改又不是很懂,还有像是Github的action脚本也会用到这些。Shell即贝壳的意思,它就像套在Linux内核的一种抽象接口,对内连接内核,对外为用户提供命令接口,bash便是其中一种 ^1:

Shell 接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell 会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。这种特殊字符的扩展,称为模式扩展(globbing)。
2. 内容
2.1 Shebang 行
脚本的第一行通常是指定解释器,即这个脚本必须通过什么解释器执行。这一行以#!
字符开头,这个字符称为 Shebang,所以这一行就叫做 Shebang 行。#!
后面就是脚本解释器的位置,Bash 脚本的解释器一般是/bin/sh
或/bin/bash
。
1 |
2.2 脚本参数
调用脚本的时候,脚本文件名后面可以带有参数:
1 | ./script.sh word1 word2 word3 |
script.sh
是一个脚本文件,word1
、word2
和word3
是三个参数。而脚本文件内部,可以使用特殊变量,引用这些参数:
参数 | 意义 |
---|---|
$0 |
脚本文件名,即script.sh 。 |
$1 ~$9 |
对应脚本的第一个参数到第九个参数。 |
$# |
参数的总数。 |
$@ |
全部的参数,参数之间使用空格分隔。 |
$* |
全部的参数,参数之间使用变量$IFS 值的第一个字符分隔,默认为空格,但是可以自定义。 |
如果脚本的参数多于9个,那么第10个参数可以用${10}
的形式引用,以此类推。注意,如果命令是command -o foo bar
,那么-o
是$1
,foo
是$2
,bar
是$3
。
2.3 条件判断
if
是最常用的条件判断结构,只有符合给定条件时,才会执行指定的命令。它的语法如下。
1 | if commands; then |
以fi
结尾,if
结构的判断条件,一般使用test
命令:
1 | # 写法一 |
写法1太繁琐,方便起见使用第二种形式:
命令 | 解释 |
---|---|
[ -a file ] |
如果 file 存在,则为true |
[ -b file ] |
如果 file 存在并且是一个块(设备)文件,则为true |
[ -c file ] |
如果 file 存在并且是一个字符(设备)文件,则为true |
[ -d file ] |
如果 file 存在并且是一个目录,则为true |
[ -e file ] |
如果 file 存在,则为true |
[ -f file ] |
如果 file 存在并且是一个普通文件,则为true |
[ -g file ] |
如果 file 存在并且设置了组 ID,则为true |
[ -s file ] |
如果 file 存在且其长度大于零,则为true |
命令 | 解释 |
---|---|
[ -n string ] or [ string ] |
如果string 不为空(长度大于0),则判断为真 |
[ -z string ] |
如果字符串string 的长度为零,则判断为真 |
[ string1 == string2 ] |
如果string1 和string2 相同,则判断为真 |
[ string1 != string2 ] |
如果string1 和string2 不相同,则判断为真 |
[ string1 '>' string2 ] [^2] |
如果按照字典顺序string1 排列在string2 之后,则判断为真。 |
[ string1 '<' string2 ] |
如果按照字典顺序string1 排列在string2 之前,则判断 |
命令 | 解释 |
---|---|
[ integer1 -eq integer2 ] |
如果integer1 等于integer2 ,则为true |
[ integer1 -ne integer2 ] |
如果integer1 不等于integer2 ,则为true |
[ integer1 -le integer2 ] |
如果integer1 小于或等于integer2 ,则为true |
[ integer1 -lt integer2 ] |
如果integer1 小于integer2 ,则为true |
[ integer1 -ge integer2 ] |
如果integer1 大于或等于integer2 ,则为true |
[ integer1 -gt integer2 ] |
如果integer1 大于integer2 ,则为true |
2.4 数组
bash数组的定义:
1 | # 变量定义的`=`前后不要有空格,否则会被解释为命令,而数组元素定义用空格分割 |
数组元素选取:
${array[i]}
:取第i
个元素${array[@]}
:读取所有元素array+=(d e f)
:追加元素d、e、f
还有一种数组在bash中叫关联数组,其实就是(key,value)
键值对集合即字典:
1 | declare -A colors |
${colors["blue"]}
:字典读取
2.5 循环
这里只介绍一种格式,其余都是类似的:
1 | number=0 |
和其他语言一样,亦可以使用continue
和break
,另外还有一种特别的循环类型:
1 | select name in list |
这种方式是bash中特有的,运行后会出现一个单选框,只能选择其中一个:
1 |
|
2.6 函数
函数的定义和其他语言一样:
1 | function fn() { |
函数定义的定义也与其他语言一样,function
关键字可写可不写,在函数体内定义局部变量则用local
关键字,如果不使用local直接定义,则为全局变量(尽管在函数体内)。
3. Reference
[^2]: test
命令内部的>
和<
,必须用引号引起来(或者是用反斜杠转义)。否则,它们会被 shell 解释为重定向操作符