Bash 基本介绍

2015-09-23 bash language

一些与 Bash 相关的内容,如命令执行顺序、配置文件、通配符、元字符及转义字符等。

命令执行顺序

Shell 一般会按照 alias keyword function built-in $PATH 的顺序进行搜索。

在执行完命令之后会保存在一个 hash 表中,下次直接通过 hash 查找,如果将一个命令删除可能会出现 No such file or directory 的错误;可以通过 set -h 启用 hash 功能,set +h 禁用。

可通过 hash 查看当前列表,hash -d command 删除该记录,hash -r 删除所有记录,重新搜索。

通过 hash 命令查看时,其第一列为使用的次数,注意不会缓存 functionbuilt-in 以及部分 alias;注意,不会缓存包含绝对路径的 alias 命令。

可以通过 alias cmd 查看定义的 alias ,一般通过 alias cmd='xxx' 定义别名,unalias cmd 删除别名。

常见操作可以参考如下:

----- 可以查看该命令的所有类型
$ type -a cmd
----- 查看执行时的类型
$ type cmd

----- 查看所有的built-in命令
$ enable
----- 禁用built-in的cmd命令
$ enable -n cmd
----- 启用built-in的命令
$ enable cmd

配置文件

Bash 的很多配置文件,要说清楚这些配置文件的区别,则首先要了解 login shell 和 no login shell 的区别。

  • login shell 指的是完整的登录流程,需要输入用户名和密码,例如 tty1~tty6 等。
  • no login shell,简单来说是 XWindow 登陆后又启动了多个终端,此时不需要输入密码。

Bash 配置文件包括全局配置文件和用户相关的局部配置文件。

全局变量

全局配置文件 /etc/profile ,在任何用户第一次登陆时 (或在切换用户时使用 - 参数) 都会读取该文件。

另外一个是 /etc/bashrc ,其中 Ubuntu 没有这个文件,与之对应的是 /etc/bash.bashrc ,会在 bash 执行时会读取此文件。

局部变量

在执行完全局变量后,执行用户指定的配置文件,依次检查 ~/.bash_profile ~/.bash_login ~/.profile 最先找到的直接执行,然后退出。

其中相关的配置文件有如下:

  • ~/.bash_profile Ubuntu 默认没有此文件,可新建,只有 Bash 是以 login 形式执行时,才会读取此文件,通常来说该配置文件还会配置成读取 ~/.bashrc
  • ~/.bash_login 若 bash 是以 login 方式执行时,读取 ~/.bash_profile ,若它不存在,则读取 ~/.bash_login,若两者都不存在,读取 ~/.profile
  • ~/.profile 除了上述的配置文件执行方式外,在图形模式登录时,此文件被读取,即使存在 ~/.bash_profile~/.bash_login
  • ~/.bashrc 当 Bash 是以 non-login 形式执行时,读取此文件,若以 login 形式执行,则不会读取此文件,但是通常在上述的三个文件中会调用该文件。
  • ~/.bash_logout 注销时,且是 login 形式,此文件才会读取。也就是说,在文本模式注销时,此文件会被读取,图形模式注销时,此文件不会被读取。

读取顺序

login shell 和 non-login shell 读取的配置文件数据并不一样。

----- login shell会读配置文件,后面的三个读取一个文件后就会退出
/etc/profile ~/.bash_profile或~/.bash_login或~/.profile

----- non-login shell会读配置文件
~/.bashrc

通配符、元字符及转义字符

介绍一些与之相关的概念。

通配符

通配符是由 shell 处理的,在遇到了通配符时,shell 会将其当作路径或文件名去在磁盘上搜寻可能的匹配:若符合要求的匹配存在,则进行代换 (路径扩展);否则就将该通配符作为一个普通字符传递给 “命令”,然后再由命令进行处理。

总之,通配符实际上就是一种 shell 实现的路径扩展功能,在通配符被处理后,shell 会先完成该命令的重组,然后再继续处理重组后的命令,直至执行该命令。

常见示例如下:

*               匹配0或多个字符,a*b: acb, a123db
?               匹配任意单一字符,a?b: acb, a1b
[list]          匹配list中的任意单一字符,a[xyz]b: axb, ayb, azb
[!list]         匹配除list中的任意单一字符,a[!0-9]b: aab, acb, a-b
[c1-c2]         匹配c1到c2中的任意单一字符,a[0-9]b: a0b, a1b
{str1, str2}    匹配str1或str2中的任意字符串,a{ab, cd}b: aabb, acdb

元字符

Shell 除了有通配符之外,由 shell 负责预先先解析后,将处理结果传给命令行之外,shell 还有一系列自己的其他特殊字符。

IFS      由 space 或 tab 或 enter 三者之一组成(我们常用 space )。
CR       由 enter 产生。
=        设定变量。
$        作变量或运算替换(请不要与 shell prompt 搞混了)。
>        重导向 stdout。
<        重导向 stdin。
|        命令管线。
&        重导向 file descriptor ,或将命令置于背境执行。
( )      将其内的命令置于 nested subshell 执行,或用于运算或命令替换。
{ }      将其内的命令置于 non-named function 中执行,或用在变量替换的界定范围。
;        在前一个命令结束时,而忽略其返回值,继续执行下一个命令。
&&       在前一个命令结束时,若返回值为 true,继续执行下一个命令。
||       在前一个命令结束时,若返回值为 false,继续执行下一个命令。
!        执行 history 列表中的命令。

转义字符

有时候,我们想让通配符,或者元字符变成普通字符,不需要使用它。那么这里我们就需要用到转义符了。shell提供转义符有三种。

''      硬转义,其内部所有的shell 元字符、通配符都会被关掉。注意,硬转义中不允许出现'(单引号)。
""      软转义,其内部只允许出现特定的shell 元字符:$用于参数代换 `用于命令代替 \用于转义。
\       转义,去除其后紧跟的元字符或通配符的特殊意义。

Bash 历史

输入命令时 Bash 将其保存在内存中,其大小由 HISTSIZE 决定,在 Bash 退出时将 HISTFILESIZE 的最近的命令保存在 HISTFILE 中,在 ~/.bash_profile 中可以修改设置。

在启动 Bash 时会从 HISTFILE 读入 HISTSIZE 大小的命令行,通常在写入历史文件时使用的是覆盖方式,如果需要以追加方式添加可以 shopt -s listappend

----- 显示命令执行的时间戳,之前的命令不会
$ export HISTTIMEFORMAT='%F %T '
----- 剔除连续重复的条目,erasedups剔除整个历史中重复的条目ignorespace在不想被记住的命令前加上空格
$ export HISTCONTROL ignoredups
----- 忽略特定的命令
$ export HISTIGNORE="pwd:ls:ls -ltr:"

可以通过 Ctrl-RCtrl-S 来对历史进行搜索,通过 Ctrl-G 可以复位,更多快捷键可参考 Bash Reference Manual 文档。

history            显示所有的历史命令,包括序号。
history N          显示最近的N条历史命令。
history -c         清楚所有的历史命令。
history -d N       清除第N条历史命令。
!string            用来查找最近的以string开头历史命令。
!?string           用来查找最近含有string的命令,不是严格以string开头历史命令。
^string1^string2^  将上一条命令中的string1替换为string2。
!number            执行历史中的第number条命令。
!!                 执行上一条命令。
!-number           执行最近的第N条命令。
!$ <<==>> !!:$     获得上一条命令的最后一个参数。
!^ <<==>> !!:^     获得上一条命令的第一个参数。
!cp:2              查找最近以cp开头的命令,并取得第二个参数。

示例:
$ echo a b c d e
a b c d e
$ echo !!:2
b