shell命令用法分为:
* 单一命令:最常见的类型
* 管道:多干命令之间通过输入输出连接
* 列表:按顺序执行多个命令
* 复合命令:控制流命令
* 进程交互:命令间的双向交互
* 并行计算
3.2.1 简单命令
一般就是空格隔开的一系列单词,通常以一个控制操作符结尾。(控制操作符就是前面介绍的:换行符 或者 ‘||’, ‘&&’, ‘&’, ‘;’, ‘;;’, ‘|’, ‘|&’, ‘(’, or ‘)’.
,看到这里我们不禁想起那些复合语句为什么需要分号,是不是也是这个原因,等着看下面的章节)。
命令的返回状态就是命令的状态码,由waitpid函数提供,或者,如果命令被一个信号结束,那么返回值会是是一个128+n的值。(说道这里,我们不禁想起,为什么和waitpid有关系?原因是shell是我们执行命令的父进程,而shell 会调用waitpid等待命令执行完毕,并获取命令进程的状态,这应该就是这里说的意思,但不确定。)
3.2.2 管道流
这里直接说管道流不是非常合适,因为这里说的管道,因为对应的是pipelines,是包括管道符在内的一些列命令。而且这些命令是用两个控制操作符分隔的,这两个操作符是 | 和 |&,管道流中的每个命令都在他们自己的subshell中执行,应该就是每个命令有独立的子进程执行。所以退出状态也就是最后一个命令的退出状态。
3.2.3 列表
列表的定义是,一个或者多个pipeline,以‘;’, ‘&’, ‘&&’, or ‘||’
分隔,同时选择性得以‘;’, ‘&’, 换行
结尾。(看来分号很强大,既可以是分隔,也可以是结束),操作符中,‘&&’, ‘||’
优先级相同,‘;’, ‘&’
优先级相同。
领表以一行或者多行的形式出现也是可能的,目的是用来分清命令,这个和分号的功能一样。
(这部分还说有一段懒得翻译)
3.2.4符合语句
分为三种:
* 循环结构:针对重复的行为
* 条件结构:条件化执行
* 命令组:对命令进行分组
3.2.4.1 循环语句
注意以下两条语句:
n=0; while [[ n -lt 10 ]]; do echo n; ((n++)); done
n=0; while [ n -lt 10 ]; do echo n; ((n++)); done
第一条执行成功,第二条失败,提示integer expression expected。但是我们就是整数表达式。为题出现在n,语句中的n并不是整数,test确实支持 INTEGER1 和 INTEGER2的比较,但是编译器并不认为n是整数,怎么办,这就需要明确把值打印出来,用$n就可以:n=0; while [ $n -lt 10 ]; do echo n; ((n++)); done
,但是为什么[[ ]]
就可以直接用n,看文档,似乎只看到说[[支持variable expansion,什么意思,难道就是n可以直接换成值么。
其实,这种算数运算,一般可以直接用(()),比如:
`n=0; while (( n < 10 )); do echo n; ((n++)); done
非常好用。
还有一个比较有意思:
n=0; while [ !]; do echo n; ((n++)); done
就是死循环,因为[]
默认是返回false,所以加上!就一直是true。
3.2.4.3 命令组
两种方式: (list)和{list;}
两点区别,第一,()是起一个subshell来执行,而{}是直接在当前shell执行。第二,()是被当作运算符,而{}是被识别为保留字,所以{和list之间必须被空格,或者其他元字符隔开。而运算符就不需要,它会被识别为单独的标记(token),所以解释器解析时并不一样。
所以在shell下如果直接执行:> (echo hello)
是没问题的,但是执行:>{echo hello;}
就有问题,{和echo之间需要有空格。同时,需要注意{}里的list后面分号。