Bash
课程概览与 shell · the missing semester of your cs education
Bourne Again SHell, 简称 “bash”
ls -l |
foo=bar |
和其他大多数的编程语言一样,bash
也支持 if
, case
, while
和 for
这些控制流关键字。同样地, bash
也支持函数,它可以接受参数并基于参数进行操作。下面这个函数是一个例子,它会创建一个文件夹并使用 cd
进入该文件夹。
mcd () { |
这里 $1
是脚本的第一个参数。与其他脚本语言不同的是,bash 使用了很多特殊的变量来表示参数、错误代码和相关变量。下面列举了其中一些变量,更完整的列表可以参考 这里。
$0
- 脚本名$1
到$9
- 脚本的参数。$1
是第一个参数,依此类推。$@
- 所有参数$#
- 参数个数$?
- 前一个命令的返回值$$
- 当前脚本的进程识别码!!
- 完整的上一条命令,包括参数。常见应用:当你因为权限不足执行命令失败时,可以使用sudo !!
再尝试一次。$_
- 上一条命令的最后一个参数。如果你正在使用的是交互式 shell,你可以通过按下Esc
之后键入 . 来获取这个值。
命令通常使用 STDOUT
来返回输出值,使用 STDERR
来返回错误及错误码,便于脚本以更加友好的方式报告错误。 返回码或退出状态是脚本/命令之间交流执行状态的方式。返回值 0 表示正常执行,其他所有非 0 的返回值都表示有错误发生。
退出码可以搭配 &&
(与操作符)和 ||
(或操作符)使用,用来进行条件判断,决定是否执行其他程序。它们都属于短路 运算符(short-circuiting) 同一行的多个命令可以用 ;
分隔。程序 true
的返回码永远是 0
,false
的返回码永远是 1
。让我们看几个例子
false || echo "Oops, fail" |
另一个常见的模式是以变量的形式获取一个命令的输出,这可以通过 命令替换(command substitution)实现。
当您通过 $( CMD )
这样的方式来执行 CMD
这个命令时,它的输出结果会替换掉 $( CMD )
。例如,如果执行 for file in $(ls)
,shell 首先将调用 ls
,然后遍历得到的这些返回值。还有一个冷门的类似特性是 进程替换(process substitution), <( CMD )
会执行 CMD
并将结果输出到一个临时文件中,并将 <( CMD )
替换成临时文件名。这在我们希望返回值通过文件而不是 STDIN 传递时很有用。例如, diff <(ls foo) <(ls bar)
会显示文件夹 foo
和 bar
中文件的区别。
说了很多,现在该看例子了,下面这个例子展示了一部分上面提到的特性。这段脚本会遍历我们提供的参数,使用 grep
搜索字符串 foobar
,如果没有找到,则将其作为注释追加到文件中。
|
在条件语句中,我们比较 $?
是否等于 0。 Bash 实现了许多类似的比较操作,您可以查看 test 手册
。 在 bash 中进行比较时,尽量使用双方括号 [[ ]]
而不是单方括号 [ ]
,这样会降低犯错的几率,尽管这样并不能兼容 sh
。 更详细的说明参见 这里。