Linux系统学习笔记:shell环境


Linux系统学习笔记:shell环境
 
Linux系统中包含强大的shell环境,作为命令解释器。通过shell环境不仅可以和大量的命令行工具进行交互,而且shell还支持脚本编程,以批处理的方式完成更为复杂耗时的工作。BASH是目前绝大多数Linux版本的默认shell解释器。本篇我们以BASH为基础总结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环境中一些键的作用:
 
Backspace  Delete  ^H 删除字符
^W 删除单词
^U 删除行
^C 中断
^Z 挂起
^D 退出当前用户登录
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 )命令。
 
还可以用 ! 引用事件(即命令):
 
!! 执行前一个命令
!n 执行历史列表编号为n的命令,n为负值时,执行最近第|n|条命令
!str 执行最近以str开头的命令
!?str[?] 执行最近包含str的命令,后面的?是可选的
!# 当前命令已经输入的部分
!{event} {}将event和左右文本隔开
命令可以使用字标志符和修饰符进行一些修改和替换等。
 
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
~扩展
~ 代替 HOME 变量的值。如果 ~ 后面跟一个合法的用户名,那就会替换为该用户的主目录。在目录栈中, ~+为当前工作目录, ~- 为前一个工作目录。
 
$ echo ~root
/root
算术扩展
$((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
命令替换
命令替换的语法有两种: $(cmd) 和 `cmd` ,它们用命令的输出替代该命令。
 
$ ls -l $(find . -name README -print)
路径扩展
对于包含特殊字符的文件名,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 设置变量属性,有以下选项:
 
-a 声明数组变量
-f 声明函数变量
-i 声明整型变量
-r 声明只读变量,等价于  readonly
-x 输出变量(设置为全局变量),等价于  export
如果将选项的前导 - 改为 + ,可以删除特定属性。不带参数时,列出所有特定类或全部的变量。
 
关键字变量
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 。

相关内容

    暂无相关文章