种类(常见)
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- Shell for Root(/sbin/sh)
特点
- 行与行: 无需以分号结尾, 若想一行执行两句命令可用分号作分隔
- 赋值: 赋值时等号两边不能有空格, 作为判断符时等号两边必须有空格
操作
- 解释器声明:
#!/bin/bash(#!后接上 要使用的解释器的路径) - 运行:
./test.sh #执行脚本或/bin/sh test.sh #指明解释器并运行 - 注释:
#单行注释和{多行注释,代码括起来当作函数,以注释}和: '多行注释,冒号后要有空格'
变量
定义:不用$符号 定义过的变量可再次定义
RUNOOB="www.runoob.com"
LD_LIBRARY_PATH="/bin/"
_var="123"
var2="abc"
引用:需要$符号
your_name="qinjx"
echo $your_name
echo ${your_name}
引用花括号是可选的, 加花括号是为了帮助解释器识别变量的边界, 如以下情况
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
只读变量:用readonly定义,相当于常量
myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com" #这行赋值会失败
删除变量:unset
unset variable_name
数据类型
-
布尔值: true与false, 条件语句中, 空被视为false, 非空被视为true
-
字符串变量: 用单引号
''或双引号""来定义双引号字符串内可以有变量(一般要有花括号),识别命令替换,单引号字符串不行(转义字符与单双引号无关,与输出命令有关) shell的单引号可以跨行 my_string='Hello, World!' my_string="Hello, World!" -- 字符串拼接 -- your_name="runoob" # 使用双引号拼接 greeting="hello, "$your_name" !" greeting_1="hello, ${your_name} !" echo $greeting $greeting_1 #输出结果为 hello, runoob ! hello, runoob ! # 使用单引号拼接 greeting_2='hello, '$your_name' !' greeting_3='hello, ${your_name} !' echo $greeting_2 $greeting_3 #输出结果为 hello, runoob ! hello, ${your_name} ! -- 提取子字符串 -- ${字符串变量:下角标a:下角标b} 获取从a到b的子字符串(包括a与b) string="runoob is a great site" echo ${string:1:4} # 输出 unoo -- 获取字符串长度 -- ${#字符串变量:下角标a:下角标b} 在前边加上#即可获取子字符串包含的字符个数 ${#string} 等价于 ${#string:0} string="abcd" echo ${#string:0} # 输出 4 -- expr -- 字符串长度计算: expression length <字符串> (返回字符串长度) 字符串截取: expression substr <字符串> <起始位置a> <截取长度b> (a从1开始计数,截取的字符串包含a所代表字符) 字符串比较: expression <字符串1> = <字符串2> (比较结果为真时返回1,为假时返回0) 查找字符第一次出现位置: expression index <字符串> <字符> (返回字符第一次出现的位置,计数从1开始,若字符为多个,则返回所有字符中最先出现的,没找到则返回0) -
数组变量: bash支持一维数组(不支持多维数组), 并且没有限定数组的大小
--定义-- array_name=(value0 value1 value2 value3) --值之间用空白符隔开(不止包括空格) 或 array_name[0]=value0 array_name[1]=value1 array_name[n]=valuen --定义(关联数组)-- declare -A array_name=(["键"]=值 ["键"]=值 ...) 或 declare -A array_name array_name["键"]=值 array_name["键"]=值 --引用-- echo ${array_name[n]} 使用 @ 或 * 符号可以获取数组中的所有元素 echo ${array_name[@]} echo ${array_name[*]} 若再加上感叹号 ! 可以获取数组的所有键 echo ${!array_name[*]} echo ${!array_name[@]} -- 获取数组的长度 -- # 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 length=${#array_name[n]} -
其它变量
整数变量:使用 declare 或 typeset 命令来声明, 如果尝试将非整数值赋给它,Shell会尝试将其转换为整数 declare -i my_integer=42 typeset my_integer=42 数组变量:分为 索引数组 和 关联数组 索引数组 my_array=(1 2 3 4 5) 关联数组 declare -A associative_array associative_array["name"]="John" associative_array["age"]=30 环境变量:系统或用户设置的特殊变量 echo $PATH
传递参数
- 概念: 执行脚本时传入的参数可以在脚本内进行引用
- 注释: 传递参数在命令行中为空
| 参数处理 | 说明 |
|---|---|
| $n | n 代表一个数字, 0代表脚本名称, 为1则代表执行脚本的第一个参数, 为2代表第二个参数 |
| $# | 传递到脚本的参数个数 |
| $* | 以一个单字符串显示所有向脚本传递的参数如"$*"用「"」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
| $$ | 脚本运行的当前进程ID号 |
| $! | 后台运行的最后一个进程的ID号 |
| $@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 如"$@"用「"」括起来的情况、以"$1" "$2" … "$n" 的形式输出所有参数。 |
| $- | 显示Shell使用的当前选项,与set命令功能相同。 |
| $? | 显示最后命令的退出状态, 0表示没有错误,其他任何值表明有错误 |
流程控制
-- if --
if condition1
then
command
elif condition2
then
command
else
command
fi
-- for --
for <无$变量名> in 值1 ...
do
command
done
会依次赋值为值1,值2,...
for ((初始化;条件;变化))
do
command
done
-- while --
while condition
do
command
done
其中condition为 : 或 true 时为无限循环
-- until --
与while相反,当condition为false时循环
until condition
do
command
done
-- case --
类似于switch
case 值 in
<值1>)
command
;;
<值2>|<值3>|...)
command
;;
...
*)
command
;;
esac
-- 其它 --
break: 跳出循环
continue: 开始下一次循环
花括号展开
- 介绍: {a..b}代表从a到b的参数, 还可以{a..b..c}设置步长c
- 特点: {a..b}并不是代表包含从a到b元素的数组, 而是 a 到 b 的参数, 常用于for in循环
- 例子:
ls {1..5..2}等价于ls 1 3 5
输入与输出
-- echo --
echo <字符串> ...
-e 启用转义字符,bash默认不启用,zsh默认启用,不启用则会原样输出含有的转义字符
-n 取消换行符,echo默认会在输出后换行
特点: 输出的字符串可以没有引号,可以输出多个字符串
-- printf --
printf <格式化字符串> [<参数> ...]
特点:printf默认识别转义字符,但不会在输出后换行,
-- read --
read <变量> ...
作用:读取标准输入,直到读取到换行符,通过空白符来分隔字段,并将字段按顺序赋值给变量
赋值:若字段多于变量数,多余字段不会被分隔,而是整个赋值给最后一个变量;若字段少于变量数,未被赋值的变量会为空
特点:被赋值变量存储的不是字符串,而是类似于在使用该变量时直接将内容替换到对应位置, 所以可能会因为空白符被当成多个参数, 若想其被当作一个字符串, 可以用双引号包围 如 "$<变量>"
-- 命令替换 --
命令替换:可以用反引号 ` ` 或 $() 包围命令,使命令的输出变为返回值, 从而嵌套在其它指令中
特点:命令替换的返回值并不会被当成一个字符串,而是类似于将命令的输出直接替换到对应位置, 所以可能会因为空白符被当成多个参数, 若想其被当作一个字符串, 可以用双引号包围 如 "\`内容\`"和"$()"
test命令
- 介绍: test命令为有各种功能的条件表达式
- 形式:
test <condition>或[ <condition> ] - 注意: condition中数值与运算符间要有空格, 使用方括号时括号内的元素与方括号之间需有空格
- 特殊: 若使用&&与|充当 与 或 , 则要用两个中括号
| 参数 | 说明 | 元素 |
|---|---|---|
| -a | 与 | 布尔值或其它 |
| -o | 或 | 布尔值或其它 |
| ! | 非 | 布尔值或其它 |
| -eq | 等于 | 数值 |
| == | 等于 | 数值 |
| -ne | 不等于 | 数值 |
| != | 不等于 | 数值 |
| -gt | 大于 | 数值 |
| -ge | 大于等于 | 数值 |
| -lt | 小于 | 数值 |
| -le | 小于等于 | 数值 |
| = | 等于 | 字符串 |
| != | 不相等 | 字符串 |
| -z 字符串 | 字符串的长度为零 | 字符串 |
| -n 字符串 | 字符串的长度不为零 | 字符串 |
| -e 文件名 | 如果文件存在则为真 | 文件 |
| -r 文件名 | 如果文件存在且可读则为真 | 文件 |
| -w 文件名 | 如果文件存在且可写则为真 | 文件 |
| -x 文件名 | 如果文件存在且可执行则为真 | 文件 |
| -s 文件名 | 如果文件存在且至少有一个字符则为真 | 文件 |
| -d 文件名 | 如果文件存在且为目录则为真 | 文件 |
| -f 文件名 | 如果文件存在且为普通文件则为真 | 文件 |
| -c 文件名 | 如果文件存在且为字符型特殊文件则为真 | 文件 |
| -b 文件名 | 如果文件存在且为块特殊文件则为真 | 文件 |
| -u 文件名 | 如果文件存在且设置了SUID位则为真 | 文件 |
| -g 文件名 | 如果文件存在且设置了SGID位则为真 | 文件 |
| -k 文件名 | 如果文件存在且设置了粘着位(Sticky Bit)则为真 | 文件 |
| -p 文件名 | 如果文件存在且是有名管道则为真 | 文件 |
| -L 文件名 | 如果文件存在且是socket则为真 | 文件 |
| -S 文件名 | 如果文件存在且是符号链接则为真 | 文件 |
计算
- 计算方法
expr $[] $(()) (())(注:都只能进行整数运算 let与(())很像, 不过多赘述)
expr的运算数与运算符要用空格隔开,且乘号(*)前边必须加反斜杠(\)才能实现乘法运算,且expr会输出运算结果
$[] $(()) (()) 中可以在其内进行算数运算与赋值(赋值等号旁边可以有空格,运算符与运算数可以不隔开),以及引用变量(引用时可以不用$),还可进行判断 < > <= >= == !=,返回值为1或0
其中$[] $(())有返回值,(())没有返回值;但(())充当条件语句时有返回值
$(())与()可以进行 ++自增 --自减 +=等复合赋值运算, $[]不行 - 特点
可以引用未定义变量 进行复合赋值运算, 此时其值被当为0
| 运算符 | 说明 | 举例 |
|---|---|---|
+ |
加法 | expr $a + $b $[$a+$b] (($a+$b)) |
- |
减法 | expr $a - $b $[$a-$b] (($a-$b)) |
* |
乘法 | expr $a \* $b $[$a*$b] (($a*$b)) |
/ |
除法 | expr $b / $a $[$a/$b] (($a/$b)) |
% |
取余 | expr $b % $a $[$a%$b] (($a%$b)) |