shell环境
在文本界面或者图形界面的终端模拟窗口中,shell作为命令解释器运行,称为shell环境。有多个版本的shell,通常BASH用的较多。
BASH通过 /etc/profile 文件进行全局配置。登录时,会查找并执行 ~/.bash_profile 、 ~/.bash_login、 ~/.profile ,注销时执行 ~/.bash_logout 。非登录还会执行 /etc/bashrc 和 ~/.bashrc 文件。非交互的BASH不执行这些初始化文件中的命令,只继承它们设置的变量,并且执行 BASH_ENV 环境变量指定的文件中的命令。
一般需要修改默认的环境变量时,在profile文件( ~/.bash_profile 、 ~/.profile 、 /etc/profile )中修改。而命令如命令别名在rc文件( ~/.bashrc 、 /etc/bash.bashrc )中修改。
shell命令在键入回车之后执行,在此之前可以修改。
下面是shell环境中一些键的作用:
shell中输入的命令的语法是:
cmd [arg] ... [arg]
通常开始为命令名,后面接可选的参数。以 - 或 -- 开头的参数也称为选项,一般放在普通的参数之前,由命令解释, - 开头的选项通常可以合并。可以使用 -- 来表示后面的参数不解释为选项。
shell在 PATH 环境变量指定的路径下查找用户拥有执行权限的程序。
shell中的特殊字符包括:
` ! # $ % ^ & * + ~ \ | ; ' " / ? < > ( ) [ ] { }
在特殊字符前加上 \ 可以对特殊字符进行转义,也可以通过使用单引号将它们括起来。输入控制字符可以先按 ^V 。
; 号可以分隔多条命令,但不立即执行它们。对于单条命令过长时,可以使用 \ 换到下一行继续输入。 ()可以对命令分组,shell为每组命令创建一个子shell,把它们作为一个作业。
# 开始行注释。 && 和 || 为逻辑与和逻辑或,连接命令可以做短路判断。 ! 反转命令的退出状态值。
此外, . 在行首时执行命令。
重定向
一个程序的进程会打开3个文件描述符,分别是标准输入(0)、标准输出(1)和标准错误输出(2)。一般情况下,标准输入是键盘,标准输出和标准错误输出是shell输出,可以通过重定向来改变标准输入输出的关联。 < 重定向标准输入( 0< 的简写), > 重定向标准输出( 1> 的简写), 2> 重定向标准错误输出, >> 将标准输出追加到文件, << 将脚本的内容重定向为脚本的输入。
<< 重定向的内容称为Here文档,使用一个或多个符号来界定,开头的界定符必须紧挨 << ,结尾的界定符必须独占一行。
重定向会覆盖已有文件,可以设置 noclobber 来禁止重定向时重写,而 >| 则可以忽略 noclobber 设置。
/dev/null 称为位桶,可以将标准输出重定向到 /dev/null 来抛弃输出的内容。
$ set -o noclobber $ date --rfc-3339=seconds > d.txt $ cat d.txt 2012-03-08 16:55:46+08:00 $ date --rfc-3339=seconds > d.txt -bash: d.txt: cannot overwrite existing file $ date --rfc-3339=seconds >| d.txt $ cat d.txt 2012-03-08 16:56:00+08:00 $ set +o noclobber $ date --rfc-3339=seconds > d.txt $ cat d.txt 2012-03-08 16:56:31+08:00 $ date --rfc-3339=seconds >> d.txt $ cat d.txt 2012-03-08 16:56:31+08:00 2012-03-08 16:57:14+08:00 $ cat /dev/null > d.txt # 删除文件内容 $ grep -i alex <<+ > Alex > Harry > Nancy > + Alex
可以用 &n 代替重定向到的文件名, n 为文件描述符。重定向到 &- 表示关闭该描述符。
$ cat a file a $ cat b cat: b: No such file or directory $ cat a b > out # 重定向标准输出到out cat: b: No such file or directory $ cat out file a $ cat a b 1> out 2>&1 # 重定向标准输出到out,重定向标准错误输出到标准输出(即out) $ cat out file a cat: b: No such file or directory $ cat a b 2>&1 1> out # 重定向标准错误输出到标准输出,重定向标准输出到out cat: b: No such file or directory $ cat out file a
管道
shell环境下的管道可以将前一个命令的输出作为后一个命令的输入,管道实际上并不单独处理每条命令,而且不产生中间文件。语法为:
cmd [args] | cmd [args]
管道可以串联,也可以和重定向组合使用。
$ who | tee w.out | grep yeolar # 还生成了包含全部登录用户的w.out文件 yeolar pts/2 2012-03-08 16:13 (yeolar-pc.local)
tee 命令可以将标准输入复制到标准输出和文件。
后台运行
命令默认在前台运行,在命令执行完毕后将控制权交回shell。可以让命令在后台运行,这样可以不必等待命令执行完毕。命令或管道连接的命令序列称为作业,可以有多个作业在后台运行。同一时间运行多个作业称为多任务特性。
在命令行末尾加上 & 可以使作业在后台运行。shell会给作业分配一个作业编号。 jobs 显示作业的列表。使用 fg 命令(或 % )可以将后台作业移到前台,使用 bg 命令可以将挂起的作业移到后台运行。
$ cat & # 后台运行cat,作业号1,PID 2640;挂起sleep,作业号2 [1] 2640 $ sleep 10 ^Z [1]- Stopped cat [2]+ Stopped sleep 10 $ date --rfc-3339=s 2012-03-09 09:07:17+08:00 $ date --rfc-3339=s # 等待超过10s 2012-03-09 09:07:32+08:00 $ bg # sleep作业仍在,移到后台并运行 [2]+ sleep 10 & $ jobs # 显示作业列表,sleep因为超时而结束 [1]+ Stopped cat [2]- Done sleep 10 $ %1 # 将作业1移到前台;挂起cat,作业号1 cat ^Z [1]+ Stopped cat $ bg 1 # 将作业1移到后台 [1]+ cat & $ jobs # 显示作业列表 [1]+ Stopped cat $ fg # 将作业1移到前台;中断cat cat ^C
目录栈
dirs 命令显示目录栈, pushd 改变目录,并将目录压入目录栈,不加参数时交换栈顶的两个目录, popd将目录从栈中弹出,不加参数时弹出栈顶目录,并改变到该目录。
$ mkdir -p a/b/c $ dirs ~ $ pushd a/ ~/a ~ $ pushd b/c/ # pwd:~/a ~/a/b/c ~/a ~ $ pushd # pwd:~/a/b/c ~/a ~/a/b/c ~ $ pushd b/ # pwd:~/a ~/a/b ~/a ~/a/b/c ~ $ pushd +1 # pwd:~/a/b ~/a ~/a/b/c ~ ~/a/b $ popd +1 # pwd:~/a ~/a ~ ~/a/b $ popd # pwd:~/a ~ ~/a/b $ popd +1 ~
命令历史
HISTSIZE 、 HISTFILE 和 HISTFILESIZE 可以设置命令历史的保存数量和文件。
fc 命令可以查看( -l )、编辑(无参数或 -e )、重新执行( -s )命令。
还可以用 ! 引用事件(即命令):
命令可以使用字标志符和修饰符进行一些修改和替换等。
Readline库
BASH的命令行编辑是通过Readline库实现的。有vi和emacs两种编辑模式可选。命令行的诸如命令行补全和一些快捷键功能都是源于Readline库。
别名
BASH的另一个很方便的功能是别名,通过 alias 将命令简化。 alias 可以嵌套。一般会在BASH的rc配置文件中配置它。
$ alias alias ls='ls --color=auto' $ alias ll='ls -l'
扩展
{}扩展
{} 中以 , 分隔开的字符串会扩展成以空格符分开的字符串列表, {} 两端可以有可选的前缀和后缀,它们被加到字符串列表中每个字符串的两端。
$ touch a{1,2,3,4,5}.txt $ ls a1.txt a2.txt a3.txt a4.txt a5.txt
算术扩展
$((expr)) 会计算 expr 并用结果替代它。BASH中使用整数进行计算。在 $(()) 中变量的引用符 $ 可以省略。 let 命令也计算算术表达式的值,而且可以给它传递多个参数。
$ x=3 y=7; echo $(((x+y)/2)) 5 $ let m=(x+y)/2 n=(x+y)/m; echo $m $n 5 2
路径扩展
对于包含特殊字符的文件名,shell可以生成和已有文件的名字匹配的文件名,这称为路径扩展或通配,特殊字符称为通配符。
? 匹配单个字符, * 匹配0或多个字符, [] 匹配方括号中的任意一个字符,可以用 - 指定字符范围,还可以在字符列表前用 ! 或 ^ 表示不匹配任意一个字符。
$ touch a111 a1 a2 a3 a5 b2 b3 c5 $ echo * a1 a111 a2 a3 a5 b2 b3 c5 $ echo .* . .. $ echo a* a1 a111 a2 a3 a5 $ echo a? a1 a2 a3 a5 $ echo a[1-3] a1 a2 a3 $ echo a[!1-3] a5 $ echo a[^1-3] a5 $ echo [a-z]* a1 a111 a2 a3 a5 b2 b3 c5 $ echo [a-z]? a1 a2 a3 a5 b2 b3 c5
变量
shell变量以字母(包括 _ )和数字组成,以字母开头。全局变量又称环境变量,通常采用大写形式。使用= 号创建变量, = 两边没有空格。变量值默认以字符串形式保存。在变量名前加上 $ 来引用变量,可以在变量名两边加上 {} 来消除歧义。
赋值语句 = 右侧为空可以将值置空, unset 命令删除变量。
单引号和双引号将内容解释为字符串,单引号会阻止引用。
$ fa=a* $ echo fa fa $ echo $fa a1 a2 a3 $ echo ${fa}a a*a $ echo "$fa" a* $ echo '$fa' $fa
可以使用 declare 或 typeset 设置变量属性,有以下选项:
如果将选项的前导 - 改为 + ,可以删除特定属性。不带参数时,列出所有特定类或全部的变量。
关键字变量
HOME 变量保存用户主目录, ~ 会被shell展开为 HOME 值。
PATH 指定了shell的搜索路径,搜索路径由 : 分隔的一组路径组成。 export PATH 会使其可被子shell访问。
$ export PATH=$PATH:$HOME: # 中间的:也可省略
CDPATH 和 PATH 语法类似,它扩展了 cd 命令可进入目录的范围。
PS1 设置用户主提示符, PS2 设置用户次提示符,默认为 > , PS3 设置 select 控制结构的菜单提示符,PS4 设置BASH调试提示符。
IFS 设置分词的分隔符,默认为空白符,通常不需要对其进行修改。
更多的关键字变量可以参考 man bash 手册。
函数
函数也是一种变量,创建函数的语法为:
[function ]name () { command }
函数将一组命令放在一起,方便了调用。函数名和命令一样,执行函数只需执行函数名即可。
可以把常用的函数放在BASH的profile文件中。
shell特性
可以使用 set -o 和 set +o 开启和关闭shell的特性。BASH的特性参看 man bash 。