目录

4.2 bash常见特性

bash常见特性

/images/linux_mt/linux_mt.jpg

bash 作为外壳程序的一种,为我们提供了与操作系统内核交互的接口。bash 本身具有丰富的特性,为我们执行和管理应用提供了便利。本节我们将学习 bash 的如下特性

  1. 命令历史
  2. 命令与路径补全
  3. 命令行展开
  4. 获取命令的执行状态和执行结果
  5. 引用与快捷键
  6. 通配符
  7. IO重定向及管道
  8. 命令 hash
  9. 多命令执行

1. bash 命令历史

命令历史指的是 shell 进程会其会话中保存此前用户提交执行过的命令;于此同时 bash 提供了快捷方式,以便我们能快速执行历史命令

1.1 命令历史控制相关的环境变量

  1. HISTSIZE:shell进程可保留的命令历史的条数;
  2. HISTFILE: 持久保存命令历史的文件,默认为 ~/.bash_history
  3. HISTFILESIZE: 命令历史文件的大小;
  4. HISTCONTROL: 控制命令历史记录的方式,可选值如下
    • ignoredups:忽略重复的命令;
    • ignorespace:忽略以空白字符开头的命令;
    • ignoreboth:以上两者同时生效;

1.2 命令用法:

history [-c] [-d 偏移量] [n]
history -anrw [文件名]
history -ps 参数 [参数...]

  • -c: 清空命令历史;
  • -d offset:删除指定命令历史
  • -r: 从文件读取命令历史至历史列表中;
  • -w:把历史列表中的命令追加至历史文件中;
  • history n:显示最近的 n 条命令;

1.3 快捷方式

常见的历史命令的快捷方式如下

  1. 调用命令历史列表中的命令:
    • !#:再一次执行历史列表中的第#条命令;
    • !!:再一次执行上一条命令;
    • !STRING:再一次执行命令历史列表中最近一个以STRING开头的命令;
  2. 调用上一条命令的最后一个参数:
    • 快捷键:ESC, . - 表示先按 ESC,在按 .
    • 字符串:!$

2. 命令补全:

所谓命令补全,就是在bash 中按下 tab 键之后,bash 会自动查找以当前输入字符开头的命令。如果给定的打头字符串如果能惟一标识某命令程序文件,则直接补全;不能惟一标识某命令程序文件,再击tab键一次,会给出列表。命令查找机制 如下:

  • 优先查找内部命令;
  • 根据PATH环境变量中设定的目录,自左而右逐个搜索目录下的文件名;

路径补全 与命令补全功能类似,只是路径补全只会在给定的起始路径下,逐一匹配起始路径下的每个文件。道理很简单,如果匹配到别处的文件名,在起始目录也还是查找不到,所以补全也没什么用。

命令和路径补全是 bash 中非常好用的功能,没事多敲击几次 tab 就好。

3. 命令行展开

Linux 中有如下特殊字符,用于扩展命令的输入方式:

  • ~: 自动展开为用户的家目录,或指定的用户的家目录;
  • {}: 可承载一个以逗号分隔的路径列表,并能够将其展开为多个路径;
1
2
3
4
5
6
> /tmp/{a,b} # 相当于
> /tmp/a /tmp/b

> mkdir -pv /tmp/x/{y1/{a,b},y2}
> mkdir -v {a,b}_{c,d}
> mkdir -pv /tmp/mysysroot/{bin,sbin,etc/sysconfig/network-scripts,usr/{bin,sbin,local/{bin,sbin,etc,lib},lib,lib64},var/{cache,log,run}}

4. 获取命令的执行状态和执行结果

命令的执行状态:

  • 表示命令执行成功还是失败
  • 命令执行完成之后,其状态返回值保存于bash的 $? 特殊变量中;

命令返回值:

  • 表示命令的返回结果,或者是命令的输出内容
  • bash 中可以通过如下方式引用命令的执行结果,这在 bash 编程中非常有用
    • $(COMMAND)
    • COMMAND

5. 引用与快捷键

5.1 Linxu 中引号的效力

  • STRING可以使用引号,单引号和双引号均可用;
  • 单引号:强引用,变量引用不执行替换;
  • 双引号:弱引用,变量引用会被替换;
  • 附注: 变量引用可使用 ${name}$name

5.2 快捷键

  • Ctrl+a:跳转至命令行行首
  • Ctrl+e:跳转至命令行行尾
  • Ctrl+u:删除行首至光标所在处之间的所有字符;
  • Ctrl+k:删除光标所在处至行尾的所有字符;
  • Ctrl+l:清屏,相当于clear

6. globbing - 文件名通配

通配符指的是 bash 中的特殊字符,称为元字符,元字符不表示字符本身而是表示一定范围内的或符合匹配条件的一类字符。通过元字符达到模糊匹配的作用。需要注意的是通配符跟正则表达式是完全不同的东西,不同软件,程序中的通配符也不会完全相同。需要特别注意的是bash 中的通配机制 匹配的是整体文件名,而非部分

bash 中的元字符如下

  • *:匹配任意长度的任意字符
  • ?:匹配任意单个字符
  • []:匹配指定范围内的任意单个字符,有如下几种特殊格式:
    • `[a-z], [A-Z]: 不会区分文件名大小写,二者表示范围相同
    • [0-9], [a-z0-9]`:
    • [[:upper:]]:所有大写字母
    • [[:lower:]]:所有小写字母
    • [[:alpha:]]:所有字母
    • [[:digit:]]:所有数字
    • [[:alnum:]]:所有的字母和数字
    • [[:space:]]:所有空白字符
    • [[:punct:]]:所有标点符号
  • [^]:匹配指定范围外的任意单个字符
    • [^[:upper:]]
    • [^0-9]
    • [^[:alnum:]]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
# 练习
# 显示/var目录下所有以l开头,以一个小写字母结尾,且中间出现一位任意字符的文件或目录;
> ls -d /var/l?[[:lower:]]

# 显示/etc目录下,以任意一位数字开头,且以非数字结尾的文件或目录;
> ls -d /etc/[0-9]*[^0-9]

# 显示/etc目录下,以非字母开头,后面跟一个字母及其它任意长度任意字符的文件或目录;
> ls -d /etc/[^a-z][a-z]*

# 复制/etc目录下,所有以m开头,以非数字结尾的文件或目录至/tmp/magedu.com目录;
> cp -r /etc/m*[^0-9] /tmp/magedu.com/

# 复制/usr/share/man目录下,所有以man开头,后跟一个数字结尾的文件或目录至/tmp/man/目录下;
> cp -r /usr/share/man/man[0-9] /tmp/man/

# 复制/etc目录下,所有以.conf结尾,且以m,n,r,p开头的文件或目录至/tmp/conf.d/目录下;
> cp -r /etc/[mnrp]*.conf /tmp/conf.d/

7. IO重定向及管道

7.1 IO重定向:

IO 我的理解就是文本流,所谓 IO 重定向就是将原本输入输出一个地方的文件流重新导向另一个地方。与输入输出相关的概念如下

  1. 可用于输入的设备包括:文件、键盘设备、文件系统上的常规文件、网卡等;
  2. 可用于输出的设备包括:文件、显示器、文件系统上的常规文件、网卡等;
  3. 默认情况下,bash 为程序提供了三种标准数据流:
    • 输入的数据流;<– 标准输入(stdin),键盘;
    • 输出的数据流:–> 标准输出(stdout),显示器;
    • 错误输出流: –> 标准错误输出(stderr),显示器;

IO 重定可分为覆盖重定向和追加重定向,所谓覆盖就是如果重定向的目标是文件,会先清空文件中的内容,而追加只是在文件的结尾继续写入。IO重定向的实现如下:

  1. 输入重定向:
    • <
  2. <<: 表示创建文档,使用方式见下 cat命令
  3. 输出重定向
    • >: 覆盖重定向 == 1>
    • >>: 追加重定向 == 1>>
  4. 错误输出重定向:
    • 2>: 覆盖重定向
    • 2>>: 追加重定向
  5. 合并正常输出流和错误输出流:
    • &>
    • &>>
1
2
3
4
5
6
# 合并正常输出流和错误输出流
COMMAND > /path/to/somefile 2>&1 # 方法一
COMMAND &> /path/to/somefile     # 方法二

COMMAND >> /path/to/somefile 2>&1 # 方法一
COMMAND &>> /path/to/somefile     # 方法二

需要注意的是上述中 1,2 指代的是标准输入输出对应的文件描述符(fd, file descriptor)。文件描述符是操作系统的一个抽象概念,表示打开的文件。大家可以理解为 Linux中一切皆文件,如果要操作文件必须将文件关联到某个文件描述符。bash 在开启时,会自动做如下关联

  • 标准输入:0
  • 标准输出:1
  • 错误输出:2

Linux 中有一个特殊设备/dev/null,它会丢弃接收到的所有输入,又称数据黑洞。通常在 shell 编程中,我们只需要知道命令的执行状态,而无需命令的执行结果时,可以将输出重定向至此设备

1
> head -1 /etc/passwd &> /dev/null # 判断 /etc/passwd 是否有内容

7.2 管道

管道是 Linux 提供的一种进程间交互(IPC)的一种方法。大家不必过于纠结它是个什么东西,只要知道的是,它可以把一个程序的输入变成另一个程序的输入,就像一根管道一样连接着程序与程序。管道的使用方式类似 COMMAND | COMMAND | COMMAND....,使用 | 链接多个命令即可。

1
2
3
4
# 管道与 IO重定向定义
> cat /etc/issue | tr 'a-z' 'A-Z' > /tmp/issue

> who | head -2 | tr  'a-z' 'A-Z' | tr -d '0-9' > /tmp/who.txt

7.3 bash 中对IO重定向的控制

set

  • 作用: 设置或撤销,shell 选项或位置参数的值
  1. set -C
    • 作用: 禁止覆盖输出重定向至已存在的文件;
    • 附注: 此时可使用强制覆盖输出:>|
  2. set +C
    • 作用: 关闭上述特性

7.4 重定向相关命令

cat

cat > /PATH/TO/SOMEFILE << EOF

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# EOF 表示文档创建的结束符
# 通过屏幕的输入将保存至 /PATH/TO/SOMEFILE
> cat > /PATH/TO/SOMEFILE << EOF
how are you
yes it is me
EOF

> cat /PATH/TO/SOMEFILE
how are you
yes it is me

tee命令:

tee [OPTION]... [FILE]

  • 作用: 把标准输入的数据复制到每一个文件FILE,同时送往标准输出,
  • 参数:
    • FILE: 可以有多个
  • 选项:
    • -a: 追加到给出的文件, 而不是覆盖
  • eg:COMMAND | tee /PATH/TO/SOMEFILE

8.命令 hash

所谓命令 hash 是指 bash 会缓存此前命令的查找结果。哈希是一种数据结构,通常也称为字典存储着键值对,能通过键快速的查找到对应的值。bash 内置的 hash 命令能显示和管理 bash 命令的缓存结果。

hash [options] [COMMAND]

  • 用法: - hash:列出所有的缓存结果 - hash -d COMMAND:删除 COMMAND 命令的缓存 - hash -r:清空所有缓存

9. 多命令执行

bash 中可以同时执行多条命令,命令之间可以没有关系顺序执行,也可以逻辑关系。可以理解为写在命令行的单行脚本。

  1. COMMAND1; COMMAND2;....: 多条命令互不影响,顺序执行
  2. COMMAND1 && COMMAND2: && 表示逻辑与,只有在第一条命令执行成功时,才会执行第二条命令
  3. COMMAND1 || COMMAND2: || 表示逻辑或,只有在第一条命令执行失败时,才会执行第二条命令
1
id $username || useradd $username

这里可以将 COMMAND1,COMMAND2 想象成一个逻辑判断表达式,&& 表示逻辑与,如果 COMMAND1 为False,整个表达式一定为 False,因此也就没有必要执行 COMMAND2,从样如果COMMAND1 为真,在逻辑或下,整个表达式肯定为真,也没有必要执行第二个表达式。这就是逻辑运算中短路逻辑。