Shell
简介
什么是 shell
- Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。
- Shell 既是一种命令语言,又是一种程序设计语言。
- Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问 Linux 内核的服务。
什么是 shell 脚本
Shell 脚本(shell script),是一种为 shell 编写的脚本程序,一般文件后缀为 .sh
。
shell 环境
模式
交互模式
非交互模式
基本语法
解释器
注释
echo
echo 用于字符串的输出。
- 输出普通字符串:
echo "hello, world" # Output: hello, world
- 输出含变量的字符串:
name=xiaoming echo "hello, \"${name}\"" # Output: hello, "xiaoming"
- 输出含换行符的字符串:
# 输出含换行符的字符串 echo "YES\nNO" # Output: YES\nNO echo -e "YES\nNO" # -e 开启转义 # Output: # YES # NO
- 输出含不换行符的字符串:
echo "YES" echo "NO" # Output: # YES # NO echo -e "YES\c" # -e 开启转义 \c 不换行 echo "NO" # Output: # YESNO
- 输出重定向至文件:
echo "test" > test.txt
- 输出执行结果:
echo `pwd` # Output:(当前目录路径)
printf
printf 用于格式化输出字符串。
printf 命令的语法:
printf format-string [arguments...]
参数说明:
- format-string: 为格式控制字符串
- arguments: 为参数列表。
默认,printf 不会像 echo 一样自动添加换行符,如果需要换行可以手动添加 \n
。
变量
跟许多程序设计语言一样,你可以在 bash 中创建变量。
bash 中没有数据类型,bash 中的变量可以保存一个数字、一个字符、一个字符串等等。同时无需提前声明变量,给变量赋值会直接创建变量。
变量命名原则
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线(_)。
- 不能使用标点符号。
- 不能使用 bash 里的关键字(可用 help 命令查看保留关键字)。
声明变量
访问变量的语法形式为:${var}
和 $var
。
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界,所以推荐加花括号。
word="hello"
echo ${word}
# Output: hello
只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
rword="hello"
echo ${rword}
readonly rword
# rword="bye" # 如果放开注释,执行时会报错
删除变量
使用 unset 命令可以删除变量。变量被删除后不能再次使用。unset 命令不能删除只读变量。
dword="hello" # 声明变量
echo ${dword} # 输出变量值
# Output: hello
unset dword # 删除变量
echo ${dword}
# Output: (空)
变量类型
- 局部变量 :局部变量是仅在某个脚本内部有效的变量。它们不能被其他的程序和脚本访问。
- 环境变量 :环境变量是对当前 shell 会话内所有的程序或脚本都可见的变量。创建它们跟创建局部变量类似,但使用的是
export
关键字,shell 脚本也可以定义环境变量。
常见的环境变量:
变量 | 描述 |
---|---|
$HOME
|
当前用户的用户目录 |
$PATH
|
用分号分隔的目录列表,shell 会到这些目录中查找命令 |
$PWD
|
当前工作目录 |
$RANDOM
|
0 到 32767 之间的整数 |
$UID
|
数值类型,当前用户的用户 ID |
$PS1
|
主要系统输入提示符 |
$PS2
|
次要系统输入提示符 |
字符串
单引号和双引号
shell 字符串可以用单引号 ''
,也可以用双引号 “”
,也可以不用引号。
- 单引号的特点
- 单引号里不识别变量
- 单引号里不能出现单独的单引号(使用转义符也不行),但可成对出现,作为字符串拼接使用。
- 双引号的特点
- 双引号里识别变量
- 双引号里可以出现转义字符
综上,推荐使用双引号。
拼接字符串
# 使用单引号拼接
name1='white'
str1='hello, '${name1}''
str2='hello, ${name1}'
echo ${str1}_${str2}
# Output:
# hello, white_hello, ${name1}
# 使用双引号拼接
name2="black"
str3="hello, "${name2}""
str4="hello, ${name2}"
echo ${str3}_${str4}
# Output:
# hello, black_hello, black
获取字符串长度
text="12345"
echo ${#text}
# Output:
# 5
截取子字符串
text="12345"
echo ${text:2:2}
# Output:
# 34
查找子字符串
text="hello"
echo `expr index "${text}" ll`
#查找 ll 子字符在 hello 字符串中的起始位置。
# Output:
# 3
数组
bash 只支持一维数组。数组下标从 0 开始,下标可以是整数或算术表达式,其值应大于或等于 0。
创建数组
# 创建数组的不同方式
nums=([2]=2 [0]=0 [1]=1)
colors=(red yellow "dark blue")
访问数组元素
- 访问数组的单个元素:
echo ${nums[1]}
# Output: 1
- 访问数组的所有元素:
echo ${colors[*]}
# Output: red yellow dark blue
echo ${colors[@]}
# Output: red yellow dark blue
- 访问数组的部分元素:
echo ${nums[@]:0:2}
# Output:
# 0 1
在上面的例子中,${array[@]}
扩展为整个数组,:0:2
取出了数组中从 0 开始,长度为 2 的元素。
访问数组长度
echo ${#nums[*]}
# Output:
# 3
向数组中添加元素
colors=(white "${colors[@]}" green black)
echo ${colors[@]}
# Output:
# white red yellow dark blue green black
上面的例子中,${colors[@]}
扩展为整个数组,并被置换到复合赋值语句中,接着,对数组colors
的赋值覆盖了它原来的值。
从数组中删除元素
用unset
命令来从数组中删除一个元素:
unset nums[0]
echo ${nums[@]}
# Output:
# 1 2
运算符
算术运算符
下表列出了常用的算术运算符,假定变量 x 为 10,变量 y 为 20:
运算符 | 说明 | 举例 |
---|---|---|
+ | 加法 | expr $x + $y 结果为 30。
|
- | 减法 | expr $x - $y 结果为 -10。
|
* | 乘法 | expr $x * $y 结果为 200。
|
/ | 除法 | expr $y / $x 结果为 2。
|
% | 取余 | expr $y % $x 结果为 0。
|
= | 赋值 | x=$y 将把变量 y 的值赋给 x。
|
== | 相等。用于比较两个数字,相同则返回 true。 | [ $x == $y ] 返回 false。
|
!= | 不相等。用于比较两个数字,不相同则返回 true。 | [ $x != $y ] 返回 true。
|
注意:条件表达式要放在方括号之间,并且要有空格,例如: [$x==$y]
是错误的,必须写成 [ $x == $y ]
。
关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字。
下表列出了常用的关系运算符,假定变量 x 为 10,变量 y 为 20:
运算符 | 说明 | 举例 |
---|---|---|
-eq
|
检测两个数是否相等,相等返回 true。 | [ $a -eq $b ] 返回 false。
|
-ne
|
检测两个数是否相等,不相等返回 true。 | [ $a -ne $b ] 返回 true。
|
-gt
|
检测左边的数是否大于右边的,如果是,则返回 true。 | [ $a -gt $b ] 返回 false。
|
-lt
|
检测左边的数是否小于右边的,如果是,则返回 true。 | [ $a -lt $b ] 返回 true。
|
-ge
|
检测左边的数是否大于等于右边的,如果是,则返回 true。 | [ $a -ge $b ] 返回 false。
|
-le
|
检测左边的数是否小于等于右边的,如果是,则返回 true。 | [ $a -le $b ] 返回 true。
|