Shell执行控制

符号

命令执行

  • ;:连续执行指令,分割多条命令

    • 所以如果不是在一行内执行,;是可以有任意多个
  • ::内建空指令,返回值为0

  • &&, ||:逻辑与、或,全部(任意)之前的命令执行成功才会 执行下连接中的命令

“转义”

  • \\:转义字符

    • 放在指令前,取消alias
    • 特殊符号前转义,Shell将不对其后字符作特殊处理,当作 普通字符(即$, \', \"
    • 行尾表示连接下一行,回车符只起换行作用,视为空格
  • $:变量符号,表示其后字符串为一个变量

  • \', \":内部视为字符串

  • --:命令行中转义-,否则shell认为-是参数选项

    1
    2
    $ rm -- -file
    # 删除文件`-file`
    • 还可以在之前加上路径避免-被解释为参数选项
    • \''等均无效

引号

单引号''

  • 单引号括起字符都作为普通字符,变量无效

  • 单引号字串中不能出现单独的单引号,使用转义符也不行,但是 可以成对出现,作为字符串拼接使用

双引号""

  • 双引号字串中可以有变量、转义字符

反引号``

反引号扩起字符串表示Shell解释命令,执行时shell首先解释其, 以标准输出替代整个反引号

  • 括号中语句为命令,分号连接

    • ``中的表达式只需要符合C语言的运算规则 即可,甚至可以使用三目预算符、逻辑表达式
  • 命令和括号之间无空格

  • $``可以将命令输出作为变量返回值,同$()

括号

()

  • 命令组/运算表达式:其中的命令列表将在新子shell运行

    • 其中变量之后不能使用,不影响当前shell环境
    • 多个命令之间分号分隔,最后命令可以省略
    • 命令和括号之间可以无空格
  • 命令替换:等同于引号``

    • bash扫描命令行,执行$()结构中命令,将标准输出作为 匿名变量值
    • ()中出现()不需要转义,``需要转义
    • ()中不能使用C风格的运算表达式
    • 部分shell可能不支持(),如:tcsh
  • 初始化数组:参见数组

(())

  • 整数扩展:计算、扩展算数表达式结果

    • 表达式结果为0则退出状态为1、false
    • 表达式结果为1则退出状态为0、true
    1
    2
    a=5;((a++))			# 自增运算符
    b=$((16#5f)) # 进制转换
    • 退出状态和[]完全相反
    • 其中可使用任何符合C语言的运算,包括三目运算符
  • 算术比较:

    • 其中变量可以不使用$前缀、支持多个表达式逗号分隔
    • 可直接使用C风格表达式,如:forwhile循环语句中
1
2
3
4
5
6
7
for((i=0;i<5;i++))
for i in `seq 0 4`
for i iin {0..4}
# 三者等价
if ((i<5))
if [ $i -lt 5 ]
# 二者等价

[][[]]

  • []

    • 条件测试表达式:参见if
    • 数组索引
    • 正则表达式范围
  • [[]]

    • 条件测试表达式:参见if

{}

  • 创建匿名函数

    • 不开启新进程
    • 括号内变量之后可继续使用
    • 括号内命令分号分隔,最后一个语句也要有分号
    • {和第一个语句之间要有空格
  • 字符串

    • 默认值替换:参见字符串默认值替换
    • 获取子串:参见字符串子串
    • 获取切片:参见字符串子串
    • 字符串替换:参见字符串子串
  • $后包括变量名精确分隔变量名,参见变量使用

其他符号

!

Shell中!称为事件提示符,可以方便的引用历史命令:当! 后跟随字母不是空格、换行、回车、=(时,做命令替换

  • ![-]n:引用history中的正数/倒数第n个命令

    • !!:等同!-1,执行上条命令
  • !cmd:引用最近以cmd开头的命令,包括参数

    • !cmd:gs/pattern/replace:将上条cmd开头命令中 pattern替换为replace
  • !?str[?]:引用最近包含str的命令,str可以是参数

  • 参数引用

    • !$:最后一个参数
    • !:-:除最后一个参数
    • !*:所有参数

控制语句

if[]

用于条件控制结构,结构如下

1
2
3
4
if test_expression; then
then command_1
else command_2
fi
  • test <expr>:bash内部命令,判断表达式是否为真

    • 其后只能有一个表达式判断,无法使用逻辑与、或连接
  • [ <expr> ]:基本等同于test

    • 整数比较:-ne-eq-gt-lt
    • 字符串比较:转义形式大、小号\</>
    • 逻辑表达式连接:-o(或)、-a(与)、!(非) (不能使用||(或)、&&(与))
    1
    2
    3
    if [ $? == 0 ]
    if test $? == 0
    # 二者等价
    • 注意内部两边要有空格
    • 事实上是[等同于test]表示关闭条件判断,新版 bash强制要求闭合
  • [[ <expr> ]]条件测试

    • 整数比较:!==<>
    • 字符串:支持模式匹配(此时右侧模式时不能加引号)
    • 逻辑表示式连接:||(或)、&&(与)、!(非)
    1
    2
    3
    4
    if [[ $a != 0 && $b == 1 ]]
    if [ $a -eq 0 ] && [ $b -eq 1]
    if [ $a -eq 0 -a $b -eq 1]
    # 三者等价
    • [[:bash关键字,bash将其视为单独元素并返回退出 状态码

case

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case chars in
char_pattern_1)
# `)`是必要的
# 匹配即停止,不会下沉
command_1
;;
# 每个模式字符串可以有多条命令,最后一条必须以`;;`结尾
char_pattern_2 | char_pattern_3)
# `|`分隔,或,可以匹配其中一个模式即可
command_2
;;
*)
# 匹配所有字符串模式,捕获所有
command_3
;;
esac
# 返回值位最后执行命令的退出值,未执行命令则为0

while

1
2
3
4
5
6
while test_expression
# test_expression是指`test`、`[]`语句
# 测试条件为真进入循环体
do
command_1
done

until

1
2
3
4
5
until test_exprssion
# 测试条件为假进入循环体
do
command_1
done

for

CStyle

1
2
3
4
5
for ((i=0; i<limit; i++))
# C-style for
do
command_1
done

ListStyle

1
2
3
4
5
for var in var_arr
# list-style for
do
command
done
FileIterator
1
2
3
4
5
6
for var in /path/to/file_regex
# `var`依次取(当前)目录下的与正则表达式匹配的文件名
# 执行循环体语句
do
command
done
  • /path/to/file_regex注意
    • 路径不存在:$var为该字符串
    • 不能用""括起,否则:$var只取路径下所有匹配合并 ,空格分隔
ParamsIterator
1
2
3
4
5
6
for var[ in $*]
# `var`依次取位置参数的值,执行循环体中命令
# `[ in $*]`可以省略
do
command
done
RangeIterator
1
2
3
4
5
6
7
8
9
for i in $(seq start end)
do
command
done

for i in {start..end}
do
command
done

break, continue, exit

  • break[n]:跳出n层循环体,默认跳出一层循环体
  • continue[n]:跳过n层循环体在其之后的语句,回到循环开头 ,默认跳过一次循环体
  • exit:退出程序,后跟返回值
Author

UBeaRLy

Posted on

2019-08-01

Updated on

2019-08-01

Licensed under

Comments