Skip to content

6-1 命令执行顺序,管道

顺序执行多条命令

简单顺序执行

简单的顺序执行使用 ;

bash
sudo apt-get update
sudo apt-get install some-tool
some-tool

# 以上三条命令可以简化成
sudo apt-get update;sudo apt-get install some-tool;some-tool

[!hint] 如果简单顺序执行命令时,前面的命令执行不成功,而后面的命令又依赖于上一条命令的结果,那么就无法直观的判断结果是否正确,所以我们有了选择执行

选择执行

  • &&,如果 && 前面的命令执行成功,则执行 && 后面的命令
  • ||,如果 || 前面的命令执行失败,则执行 || 后面的命令
bash
# 没有安装cowsay时,什么也不发生
which cowsay>/dev/null && cowsay -f head-in ohch~
bash
# which cowsay>/dev/null成功,则执行echo "exist",echo "exist"失败,则echo "not exist"
# which cowsay>/dev/null失败,则执行echo "not exist"
which cowsay>/dev/null && echo "exist" || echo "not exist"

管道

[!quote] 管道 管道 是将上一个进程的输出,作为下一个进程的输入


  • 管道
    • 匿名管道 |:使用一些过滤程序时用到
    • 具名管道:通常只在源程序中用到

bash
echo 'hi' | cat
bash
# 不使用管道就必须把输出写到一个文件中,再去查看文件
ls -al /etc > output.txt
less output.txt

# 使用ls查看目录,并把输出的内容作为了less命令的输入
ls -al /etc | less

基于管道的文本处理命令

cut 特定部分打印

  • cut 打印每一行中的特定的部分
    • -d '分隔符' 按照分隔符将每一行分成多个字段
    • -f 字段1,……字段n 选取指定的字段
    • -c 字符数/字符范围 选取指定的字符
bash
# 打印 `/etc/passwd` 文件中以 `:` 为分隔符的第 1 个字段(用户名)和第 6 个字段(用户的home目录)
cut /etc/passwd -d ':' -f 1,6
bash
# 打印 `/etc/passwd` 文件中每一行的前 N 个字符
# 打印第五个字符
cut /etc/passwd -c 5

# 前五个(包含第5个)
cut /etc/passwd -c -5

# 打印五个之后的字符(包含第五个)
cut /etc/passwd -c 5-

# 2 到 5 之间的(包含第二个,第五个)
cut /etc/passwd -c 2-5

grep 正则表达式搜索

grep 结合正则表达式实现了复杂,高效的匹配和查找

  • grep '正则表达式' [文件]……
    • 正则表达式引擎
      • -E POSIX 扩展正则表达式【推荐
      • -G POSIX 基本正则表达式
      • -P Perl 正则表达式
    • -r 递归搜索子目录文件
    • -n 打印被匹配到目标的行号
    • -i 忽略大小写
    • -I 忽略二进制文件
    • -v 不匹配正则表达式中的内容
参数说明
-b将二进制文件作为文本来进行匹配
-c统计以模式匹配的数目
-n显示匹配文本所在行的行号
-A nn 为正整数,表示 after 的意思,除了列出匹配行之外,还列出后面的 n 行
-B nn 为正整数,表示 before 的意思,除了列出匹配行之外,还列出前面的 n 行
--color=auto将输出中的匹配项设置为自动颜色显示
bash
# 搜索`/home/shiyanlou`目录下所有包含"shiyanlou"字符的文本文件,并显示该字符出现在文本文件中的行号
grep -rnI "shiyanlou" ~
bash
# 查看环境变量中以 "yanlou" 结尾的字符串
# "."表示任何字符
# "*"表示前面的字符可以出现任意次
# "$"表示字符串的结束
export | grep ".*yanlou$"

wc 统计数目

  • wc 文件 统计并输出一个文件中行,单词,字节的数目【word count
    • -l 只统计输出行数
    • -w 只统计输出单词数
    • -c 只统计输出字节数
    • -m 只统计输出字符数
    • -L 只统计输出最长一行的字节数
bash
# 输出 `/etc/passwd` 文件的行数,单词数,字节数
wc /etc/passwd
  36   55 1914 /etc/passwd
bash
# 统计行数
wc -l /etc/passwd
bash
# 统计 /etc/ 下所有目录数
ls -dl /etc/*/ | wc -l

sort 排序

  • sort 将输入按照一定方式排序【默认字典排序】,然后再输出
    • -r 反转排序
    • -t '字段' 指定字段的分隔符
    • -k 字段号 指定对第几个字段进行排序
    • -n 按照数字排序
bash
cat /etc/passwd | sort

cat /etc/passwd | sort -r

cat /etc/passwd | sort -t':' -k 3

# 注意看第三个字段,是按照数字排序的
cat /etc/passwd | sort -t':' -k 3 -n
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin

uniq 去重

  • uniq 可以过滤重复行,或者输出重复行

过滤重复行

[!hint] uniq 只能去除连续重复的行,如果你想全文去重,那就先排序,再去重

bash
# 去除连续重复行
history | cut -c 8- | cut -d ' ' -f 1 | uniq
bash
# 全文去重
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq

输出重复行

  • uniq
    • -d 只输出重复的命令
    • -c 输出重复的命令重复的次数
    • -D 输出所有重复的行
bash
history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -dc

history | cut -c 8- | cut -d ' ' -f 1 | sort | uniq -D

tr 转换

  • tr 字符集 用来删除/转换一段文本信息中的某些文字【translate
    • 删除
      • -d 删除匹配的字符
      • -s 去除指定的在输入文本中连续并重复的字符
    • 转换 tr 字符集1 字符集2 将字符集 1 转换为字符集 2
bash
# 删除 "hello shiyanlou" 中所有的'o','l','h'
$ echo 'hello shiyanlou' | tr -d 'olh'
e siyanu
bash
# 将"hello" 中连续重复的l,去重为一个
$ echo 'hello' | tr -s 'l'
helo
bash
# 将输入的小写字母转换为大写字母
$ echo 'input some text here' | tr '[:lower:]' '[:upper:]'

col

  • col 可以将 Tab 换成对等数量的空格键,或反转此操作【column
    • -h 将空格转换为 Tab【默认】
    • -xTab 转换为空格
bash
cat /etc/protocols | col -x | cat -A

join 合并

  • join 文件1 文件2 用于合并两个文件中包含相同内容的那一行
    • -t'字符' 指定分隔符【默认为空格】
    • -i 忽略大小写的差异
    • -1 字段数 指明第一个文件要用哪个字段来对比,默认对比第一个字段
    • -2 字段数 指明第二个文件要用哪个字段来对比,默认对比第一个字段
bash
# 创建两个文件
echo '1 hello' > file1
echo '1 shiyanlou' > file2
join file1 file2

# 以':'作为两个文件字段的分隔符,再以分开的字段来匹配合并文件
sudo join -t':' /etc/passwd /etc/shadow

# 将 /etc/passwd 与 /etc/group 两个文件合并,指定以':'作为分隔符,分别匹配第4和第3个字段相同的行
sudo join -t':' -1 4 /etc/passwd -2 3 /etc/group

paste 合并

  • paste 在不对比数据的情况下,简单地将多个文件合并一起
    • -d 指定合并的分隔符【默认为 Tab
    • -s 不合并到一行,每个文件为一行
bash
echo hello > file1
echo shiyanlou > file2
echo www.shiyanlou.com > file3

paste -d ':' file1 file2 file3
hello:shiyanlou:www.shiyanlou.com

paste -s file1 file2 file3
hello
shiyanlou
www.shiyanlou.com

xargs 分段显示

  • xargs 将输出的参数列表转换成分段显示【避免参数列表过长

  • 未使用 xargs
bash
cut /etc/passwd -d ':' -f 1 | sort
_apt
backup
……
www-data
  • 使用 xargs
bash
cut /etc/passwd -d ':' -f 1 | sort | xargs
_apt backup …… www-data