- 一、变量
- 二、运算符
- 三、字符串
- 使用双引号拼接
- 使用单引号拼接
- 四、数组
- 五、函数
- 这个函数会对输入的两个数字进行相加运算…
- 输入第一个数字:
- 1
- 输入第二个数字:
- 2
- 两个数字分别为 1 和 2 !
- 输入的两个数字之和为 3 !
- 七、流程控制
- for循环一般格式为:
- 写成一行:
- 其他形式:
- 八、输入/输出重定向
- /dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
- 但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。
- 如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。
- 如果希望屏蔽 stdout 和 stderr,可以这样写
一、变量
1、命名规则
- 变量名和等号之间不能有空格
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
- 变量名中间不能有空格,可以使用下划线(_)
- 不能使用标点符号
不能使用bash里的关键字(可用help命令查看保留关键字)
2、变量声明示例如下
your_name="xxxx" √_var2=123 √user*name=tom ×,无效的变量名
3、使用变量
使用一个定义过的变量,只要在变量名前面加美元符号(只有在使用时才加$)即可,变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。建议加上
your_name="qinjx"echo $your_nameecho ${your_name} ## 帮助解释器识别变量的边界
4、只读变量
使用
readonly命令可以将变量定义为只读变量,只读变量的值不能被改变。语法:readonly var_name
5、删除变量
使用
unset命令可以删除变量。语法:unset var_name
注意:变量被删除后不能再次使用。unset 命令不能删除只读变量。
6、接收用户输入
使用
read命令用于从终端或文件读取输入,常见的用法如下:read -p “提示信息” var_name ## 打印提示符,等待输入,并将输入赋值给var_name
7、变量类型
运行shell时,会同时存在三种变量:
局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行。
二、运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如awk和expr,其中expr最常用。expr是一款表达式计算工具,使用它能完成表达式的求值操作。
1、算术运算符
| 运算符 | 说明 | 举例: a=10, b=20 |
|---|---|---|
| + | 加 | expr $a + $b 结果为 30 |
| - | 减 | expr $a - $b 结果为 -10 |
| * | 乘 | expr $a \* $b 结果为 200 转义符必须加 |
| / | 除 | expr $b / $a 结果为 2 |
| % | 取余 | expr $b % $a 结果为 0 |
| = | 赋值 | a=$b 把变量 b 的值赋给 a |
| == | 相等 | [ $a == $b ] 返回 false 空格必须加 |
| != | 不相等 | [ $a != $b ] 返回 true |
2、关系运算符
注意:关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
| 运算符 | 说明 | 举例: a=10, b=20 |
|---|---|---|
| -eq | equal,相等 == | [ $a -eq $b ] 返回 false |
| -ne | no equal,不相等 != | [ $a -ne $b ] 返回 true |
| -gt | great than,大于, > | [ $a -gt $b ] 返回 false |
| -ge | great and equal,大于等于, >= | [ $a -ge $b ] 返回 false |
| -lt | low than,小于, < | [ $a -lt $b ] 返回 true |
| -le | low and equal,小于等于, <= | [ $a -le $b ] 返回 true |
3、布尔运算符
| 运算符 | 说明 | 举例: a=10, b=20 |
|---|---|---|
| ! | 非 | [ ! false ] 返回 true |
| -o | 或 | [ $a -lt 20 -o $b -gt 100 ] 返回 true |
| -a | 与 | [ $a -lt 20 -a $b -gt 100 ] 返回 false |
4、逻辑运算符
| 运算符 | 说明 | 举例: a=10, b=20 |
|---|---|---|
| && | 逻辑与 | [[ $a -lt 100 && $b -gt 100 ]] 返回 false |
| || | 逻辑或 | [[ $a -lt 100 || $b -gt 100 ]] 返回 true |
5、字符串运算符
| 运算符 | 说明 | 举例: a=”abc”, b=”efg” |
|---|---|---|
| = | 检测两个字符串是否相等,相等返回 true | [ $a = $b ] 返回 false |
| != | 检测两个字符串是否相等,不相等返回 true | [ $a != $b ] 返回 true |
| -z | 检测字符串长度是否为0, 为0返回 true | [ -z $a ] 返回 false |
| -n | 检测字符串长度是否为0,不为0返回 true | [ -n $a ] 返回 true |
| $ | 检测字符串是否为空,不为空返回 true | [ $a ] 返回 true |
6、文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性。下面列举几个常用的测算符。
| 运算符 | 说明 | 举例:file=”/var/test.sh”,大小100字节,具有rwx权限 |
|---|---|---|
| -d file | 检测文件是否是目录,如果是,则返回 true。 | [ -d $file ] 返回 false |
| -f file | 检测文件是否是普通文件,如果是,则返回 true。 | [ -f $file ] 返回 true |
| -r file | 检测文件是否可读,如果是,则返回 true。 | [ -r $file ] 返回 true |
| -w file | 检测文件是否可写,如果是,则返回 true。 | [ -w $file ] 返回 true |
| -x file | 检测文件是否可执行,如果是,则返回 true。 | [ -x $file ] 返回 true |
| -s file | 检测文件是否为空(文件大小是否大于0),不为空返回 true。 | [ -s $file ] 返回 true |
| -e file | 检测文件(包括目录)是否存在,如果是,则返回 true。 | [ -e $file ] 返回 true |
补充知识:linux中文件类型大致分为7种 b: 块设备文件 c: 字符设备文件 d: 目录 -: 普通文件 l: 链接 s: socket p: 管道
三、字符串
1、单引号
str='this is a string'
2、单引号字符串的限制
单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
单引号字串中不能出现单独一个的单引号(对单引号转义也不行),但可成对出现,作为字符串拼接使用。
3、双引号
your_name='tom'str="Hello, I know you are \"$your_name\"! \n"echo -e $str ## echo -e 显示换行echo "OK"## Hello, I know you are "tom"!#### OK
4、双引号的优点
使用双引号拼接
greeting_0=”hello, “$your_name”!” greeting_1=”hello, ${your_name}!” echo $greeting_0 $greeting_1 ## hello, tom! hello, tom!
使用单引号拼接
greeting_2=’hello, ‘$your_name’!’ greeting_3=’hello, ${your_name}!’ echo $greeting_2 $greeting_3 ## hello, tom! hello, ${your_name}!
<a name="2ljL9"></a>#### 6、获取字符串长度```shellstring="abcd"echo ${#string} ## 4
7、提取子字符串
# 从字符串第 2 个字符开始截取 4 个字符:str="tom is a great man"echo ${str:1:4} ## om i
8、查找子字符串
# 查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):str="tom is a great man"echo `expr index "$str" io` ## 2
注意: 以上脚本中 `` 是反引号,而不是单引号‘`
四、数组
bash支持一维数组(不支持多维数组),并且没有限定数组的大小,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
1、定义数组
在shell中,用括号来表示数组,数组元素用 空格 符号分割开。
## 定义数组的一般形式为:数组名=(值1 值2 ... 值n)## 例如:array_name=(value0 value1 value2 value3 ...)## 或者:array_name=(value0value1value2value3)## 还可以单独定义数组的各个分量:array_name[0]=value0array_name[1]=value1array_name[n]=valuen## 可以不使用连续的下标,而且下标的范围没有限制。
2、读取数组
读取数组元素值的一般格式是:${数组名[下标]}
valuen=${array_name[n]}
使用@符号可以获取数组中的所有元素:echo ${array_name[@]}
3、获取数组的长度
获取数组长度的方法与获取字符串长度的方法相同,如下所示:
# 取得数组元素的个数length=${#array_name[@]}# 或者length=${#array_name[*]}# 取得数组单个元素的长度lengthn=${#array_name[n]}
五、函数
1、函数定义格式
function funname(){action;return}
说明:
无返回值
demoFun(){echo "这是我的第一个 shell 函数!"}echo "-----函数开始执行-----" ## -----函数开始执行-----demoFun ## 这是我的第一个 shell 函数!echo "-----函数执行完毕-----" ## -----函数执行完毕-----
有返回值 ```shell funWithReturn(){ echo “这个函数会对输入的两个数字进行相加运算…” echo “输入第一个数字: “ read aNum echo “输入第二个数字: “ read anotherNum echo “两个数字分别为 $aNum 和 $anotherNum !” return $(($aNum+$anotherNum)) } funWithReturn echo “输入的两个数字之和为 $? !”
这个函数会对输入的两个数字进行相加运算…
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3 !
注意:函数返回值在调用该函数后通过`$?`来获得,但是`$?`仅对其上一条指令负责,一旦函数返回后其返回值没有立即保存入参数(或者进行输出),那么其返回值将不再能通过 `$?` 获得。<a name="WVXzO"></a>### 六、参数<a name="Vs2RW"></a>#### 1、常见参数| **常见参数处理** | **说明** || --- | --- || $# | 传递到脚本的参数个数 || $* | 以一个单字符串显示所有向脚本传递的参数 || $$ | 脚本运行的当前进程ID号 || $! | 后台运行的最后一个进程的ID号 || $@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数 || $_ | 显示shell使用的当前选项,与set命令功能相同 || $? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误 |<a name="ZYydJ"></a>#### 2、脚本参数执行shell脚本时,向脚本传递参数,脚本内获取参数的格式为:`$n`。<br />n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推......<br />`$0` 为执行的文件名。```shellchmod +x test.sh./test.sh 1 3 5
vi test.shecho "Shell 传递参数实例!"; ## Shell 传递参数实例!echo "执行的文件名:$0"; ## 执行的文件名:./test.shecho "第一个参数为:$1"; ## 第一个参数为:1echo "第二个参数为:$2"; ## 第二个参数为:3echo "第三个参数为:$3"; ## 第三个参数为:5
注意:$* 与 $@ 区别
相同点:都是引用所有参数。
不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,
则 “$*” 等价于 “1 2 3”(传递了一个参数),
而 “$@” 等价于 “1” “2” “3”(传递了三个参数)
3、函数参数
在shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值。
例如:$1 表示第一个参数,$2 表示第二个参数…
funWithParam(){echo "第一个参数为 $1 !" ## 第一个参数为 1 !echo "第二个参数为 $2 !" ## 第二个参数为 2 !echo "第十个参数为 $10 !" ## 第十个参数为 10 !echo "第十个参数为 ${10} !" ## 第十个参数为 34 !echo "第十一个参数为 ${11} !" ## 第十一个参数为 73 !echo "参数总数有 $# 个!" ## 参数总数有 11 个!echo "作为一个字符串输出所有参数 $* !" ## 作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !}funWithParam 1 2 3 4 5 6 7 8 9 34 73
注意: $10不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
**
七、流程控制
1、if else 分支
if 语句语法格式:
if conditionthencommand1...commandNfi
写成一行(适用于终端命令提示符):
if [ condition ]; then command; fiif [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
if else 语法格式:
if conditionthencommand1...commandNelsecommandfi
if else-if else 语法格式:
if condition1thencommand1elif condition2thencommand2elsecommandNfi
2、for 循环
```shell
for循环一般格式为:
for var in item1 item2 … itemN do command1 … commandN done
写成一行:
for var in item1 item2 … itemN; do command1; command2… done;
其他形式:
for((assignment;condition;next));do command_1; command_2; commond_N; done;
通常情况下shell变量调用需要加 **$ **符,但是 for 中的 (()) 中不需要。<br />与 C 中相似,赋值和下一步执行可以放到代码之前循环语句之中执行,这里要注意一点:如果要在循环体中进行 for 中的 next 操作,记得变量要加 **$**,不然程序会变成死循环。<a name="zAlox"></a>#### 3、while 语句while循环用于不断执行一系列命令,也用于从输入文件中读取数据、读取键盘信息;命令通常为测试条件。其格式为:```shellwhile conditiondocommanddone
4、无限循环
## 无限循环语法格式:while :docommanddone## 或者:while truedocommanddone## 或者:for (( ; ; ))
5、until 循环
until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。
一般 while 循环优于 until 循环,但在某些时候—也只是极少数情况下,until 循环更加有用。
until conditiondocommanddone
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
6、case 语句
case语句为多选择语句。可以用case语句匹配一个值与一个模式,如果匹配成功,执行相匹配的命令。
case 值 in模式1)command1...commandN;;模式2)command1...commandN;;*)command1...;;esac
esac(就是case反过来)作为结束标记,每个case分支用右圆括号,用两个分号表示break。
取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 ***** 捕获该值,再执行后面的命令。
7、跳出循环
break命令:允许跳出所有循环(终止执行后面的所有循环)
continue命令:与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环
八、输入/输出重定向
1、重定向命令列表
| 命令 | 说明 |
|---|---|
| command > file | 将输出重定向到 file 覆盖 |
| command >> file | 将输出以追加的方式重定向到 file |
| command < file | 将输入重定向到 file |
| n > file | 将文件描述符为 n 的文件重定向到 file |
| n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file |
| n >& m | 将输出文件 m 和 n 合并 |
| n <& m | 将输入文件 m 和 n 合并 |
| << tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入 |
默认情况下,command > file 将stdout 重定向到 file,command < file 将stdin 重定向到 file。 需要注意的是: 文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
2、操作示例
stderr 重定向到 file
command 2 > file # stderr 重定向到 filecommand 2 >> file # stderr 追加到 file 文件末尾
stdout 和 stderr 合并后重定向到 file
command > file 2>&1command >> file 2>&1
对 stdin 和 stdout 都重定向
command < file1 > file2# command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。# 即command,从文件file1读取内容,然后将输出写入到file2中。
/dev/null 文件 ```shell
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出”的效果。
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null。
command > /dev/null
如果希望屏蔽 stdout 和 stderr,可以这样写
command > /dev/null 2>&1
> **注意:这里的 2 和 > 之间不可以有空格,2> 是一体的时候才表示错误输出。**5. << tag 的使用```shell## 基本形式如下:command << delimiterdocumentdelimiter## 它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。
注意:
- 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。
- 开始的delimiter前后的空格会被忽略掉。
## 在命令行中通过 wc -l 命令计算输入的行数wc -l << EOFdemo1demo2demo3333EOF## 输出结果为3
九、shell 文件包含
shell可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
## shell 文件包含的语法格式如下:. filename # 注意点号(.)和文件名中间有一空格## 或者source filename
