2MUCH

Linux-管道篇

2022-07-31


Linux-管道篇

概念

管道(pipe)可以连接两个或多个命令,将前一个命令的标准输出作为后一个的标准输入(这也就意味着,若某命令不能支持标准输出/输入的话,则无法应用管道命令)

格式:命令1 | 命令2 | ...

管道和重定向(命令1 > file)的区别:重定向是接收对象是文件,而管道是接命令的。

管道(又称无名管道)和命名管道FIFO的区别:等后面学到命名管道了再说

注意点

常见相关命令

grep (Global search REgular expression and Print out the line)

根据模式(正则表达式)对文本逐行扫描,找到并打印匹配的行

格式:

grep [options] [pattern] file
or
command | grep [options] [pattern]

[options]
	-v # 反向匹配 invert (等同于--invert-match)
	-n # 输出加上行号
	-i # 忽略大小写匹配 ignorecase
	-c # 只输出匹配的行数
	-E # 适用egrep匹配
	--color=auto # 为过滤结果添加颜色 (通常在alias中默认会有这个参数,如alias grep='grep --color=auto')
	-w # 整词对比,而不是字符
	-o # 只输出匹配到的字符串本身(匹配到多少个就会输出几行) (常用于与wc -l配合获取到匹配的个数,而不是行数)
    -q # 静默模式(stderr除外,不输出任何东西 quiet) 等同于:--quiet, --silent (不打印任何标准输出,如果有匹配的内容则返回状态值0,常用于if判断等)
    -l # 只输出匹配的文件名
    -r # 递归模式,查找所有层级子目录里的文件
[pattern]
	# 匹配模式,见正则表达式篇

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt  # 新建测试文件
i am cindy
i live in china!
I am writing in KFC.

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep "cindy"
i am cindy
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -n "KFC"
3:I am writing in KFC.
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -v "am" # 空行也会被匹配到
i live in china!

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -c "am" # 只输出匹配到的行数
2
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep "i "
i am cindy
i live in china!
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -i "i "
i am cindy
i live in china!
I am writing in KFC.
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep "c*" # 注意正则表达式和通配符的区别,正则表达式表示0个或多个'c',通配符则表示匹配c+*的字符串
i am cindy
i live in china!
I am writing in KFC.

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep "c."
i am cindy
i live in china!
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep "ci|ch"  # 没加-E只表示普通的匹配"ci|ch"字符串
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -E "ci|ch"  # 加了-E,表示匹配'ci'或'ch'
i am cindy
i live in china!
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -w "liv" # liv不是连在一起的“单词”,因为后面还跟着'e',所有无法匹配
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -w "live"
i live in china!
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -q "liv"
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo $?  
0  # 匹配到
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -q "abc"
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo $?  
1  # 没匹配到
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testGrep.txt | grep -o "in" | wc -l # 获取匹配的次数
5
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cd testGrepDir
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ cat 1.txt
i am from file1 haha
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ cat 2.txt
i am from file2 haha
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ grep -l "from" ./*  # 只输出匹配到的文件名
./1.txt
./2.txt
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ cd testGrepDir2
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir2]$ cat 3.txt
i am from file3 haha
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir2]$ cd .. 
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ grep -l "from" ./*  # 非递归模式
./1.txt
./2.txt
grep: ./testGrepDir2: Is a directory
[cindy@iZbp15qc4wmx335c268l5mZ testGrepDir]$ grep -rl "from" ./*  # 递归模式
./1.txt
./2.txt
./testGrepDir2/3.txt

cut

根据某条件(分隔符)分割输入的内容,并输出特定的分割结果。但是cut只支持单个字符的分隔符。

格式:

cut [options] file
or
command | cut [options]

[options]
	-d # 指定分割符(默认分隔符是Tab,而不是空格),常与-f配合适用。分隔符只能是单个字符。
	-f # 指定输出分割后的第几列
    -c # 指定输出某区间结果(以字符为单位)
    -b # 以字节为单位指定某区间结果
    –complement # 反选选中的部分,即输出除去该条件的内容
	–output-delimiter # 修改输出时使用的分隔符。
	--only-delimited # 不输出不包含分隔符的列。

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt  # 新建测试文件
i am cindy

it.so.hot
butiamcold
但是我冷呀
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -d '.' -f 2  # 第三行有匹配到分隔符,并输出第2个内容。其他行没有匹配到,全部输出。
i am cindy

so
butiamcold
但是我冷呀
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -d '.' -f 4  # 第三行有匹配到分隔符,但分割后只有三个子字符串,故输出为空
i am cindy


butiamcold
但是我冷呀
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -c 1  # 分割第一个字符
i

i
b
但
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -c 1-3  # 分割1-3个字符
i a

it.
but
但是我
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -d '.' -f 2,3  # 取第2和第3个分割结果
i am cindy

so.hot
butiamcold
但是我冷呀
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "12345678" | cut -c -4  # 取第4个之前的字符
1234
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "1 2 3" | cut -d ':' -f 1-  # 取第1个之后的字符
1 2 3
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "1  2" | cut -d  '  ' -f 2  # 分隔符不能指定超过单个字符
cut: the delimiter must be a single character
Try 'cut --help' for more information.
# 英文 cut -b/-c 没啥区别,但是中文就不一样了,如下所示(提醒:一个汉字对应多少个字节,要看采用的编码方式)
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "咖啡" | cut -c 1-2
咖啡
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "咖啡" | cut -b 1-2

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "咖啡" | cut -b 1-6
咖啡
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "咖啡" | cut -b 1-5
咖
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "1 2 3" | cut -d ' ' --complement -f2
1 3
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo $PATH
/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/cindy/.local/bin:/home/cindy/bin
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo $PATH | cut -d ':' -f 2-4 --output-delimiter ' '  # 分割后,取出第2到第4的内容,并替换:为空格符输出
/usr/bin /usr/local/sbin /usr/sbin
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testCut.txt | cut -d '.' -f 1- --only-delimited  # 只输出匹配到分隔符的行
it.so.hot

sort, wc, uniq

sort

针对文本文件的内容,以行为单位进行排序

sort [options] file
or
command | sort [options]

[options]
	-n # 以数字格式来大小排序(默认是以字符串格式)
	-r # 反向排序(从大到小)
	-k # 以某列进行排序
	-t # 指定分隔符(默认分割符为空格)
	-b # 忽略每行前面的空格再排序

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt
12 13 14
2 3 4
2 1 5
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt | sort  # 按照字符串格式比较,即依次比较第1,2..个字符
12 13 14
2 1 5
2 3 4
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt | sort -r
2 3 4
2 1 5
12 13 14
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt | sort -n  # 按数字格式比较,即2<12
2 1 5
2 3 4
12 13 14
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ vi testSort.txt
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt
12,13,14
2,3,4
2,1,5
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testSort.txt | sort -k 2 -t ',' -n  # 分隔符为逗号,根据第2列的数字格式排序
2,1,5
2,3,4
12,13,14

wc

用于统计文件的字节数、字数、行数

wc [options] file
or
command | wc [options]

[options]
	-c # 统计字节(char)数
	-l # 行数(line)
	-m # 字符数
	-w # 字数(word),一个字被定义为由空白、跳格或换行字符分隔的字符串。
	-L # 获取最长行的长度

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "123" | wc -c
4  # 因为echo输出会带换行符,而换行符也会被算1个,故结果是4
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "123" | wc -m
4
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "123" | wc -w
1  # 123算一个字
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ vi testWc.txt
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testWc.txt
123
4
我
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ wc testWc.txt # 参数分别为:行数,字数,字节数,文件名
 3  3 10 testWc.txt
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testWc.txt | wc -c
10
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testWc.txt | wc -m  # 注意-c和-m对于中文的长度统计不一样
8
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo -n "123" | wc -m  # echo -n 表示不输出换行符的echo
3
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testWc.txt | wc -l  # 统计行数(常用)
3

uniq

用于检查或删除重复的列,可以与sort结合使用。

uniq [options] file
or
command | uniq [options]

[options]
	- uniq filename (cat filename | unique) # 显示删除重复行的文件内容,但不改变原文件内容
	-u # 仅显示只出现一次的行(unique),与`uniq filename`效果不同
	-d # 仅显示有重复的行(dupli)
	-c # 在每一行前面标上重复的行数(count)
	-i # 忽略大小写(ignore)
	-f # 忽略比较第几栏(以空格为分割符)
# 需要注意的是,判断重复行的范围仅是相邻行。若不是相邻行的重复行,并不会被识别为重复行。若要实现将不相邻的重复行也视为重复的uniq命令,则要配合上sort命令:
	sort filename | uniq

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ vi testUniq.txt
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt
hhhhh
hhhhh
HHHHH
11111
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq  #列出去重后的结果
hhhhh
HHHHH
11111
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq -u  # 只列出不重复的行
HHHHH
11111
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq -d
hhhhh
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq -c
      2 hhhhh
      1 HHHHH
      1 11111
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq -i  # 忽略大小写后,前三行可视为相同
hhhhh
11111
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt
111
222
222

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ uniq testUniq.txt  # 输出剔重的文件内容
111
222

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt  # 但不改变原文件内容
111
222
222
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt
111
222
111
222
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat testUniq.txt | uniq -u
111
222
111
222
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ sort testUniq.txt | uniq
111
222

tee

标准输入 -> tee -> 标准输出**+文件**,即实现既将执行结果输出,并保存到文件中。

command | tee [options] filenameßß

[options]
	-a # 追加写到文件(默认是覆盖写)
	-i # 忽略中断信号
	- - ... # 重复多次
	> dev/null # 静默输出(只输出到文件)

# 注:默认会将标准输入的信息通过tee输出到文件中(即,过滤错误信息),如需要一并输出错误信息,则要结合 2>&1

例子:

[cindy@iZbp15qc4wmx335c268l5mZ ~]$ whoami | tee tee.txt
cindy  # 1、控制台输出
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat tee.txt
cindy  # 2、文件输出
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ whoami | tee tee.txt
cindy
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat tee.txt  # 覆盖写
cindy
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ whoami | tee -a tee.txt
cindy
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat tee.txt  # 追加写
cindy
cindy
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "hi" | tee tee1.txt tee2.txt  # 同时输出到多个文件
hi
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat tee1.txt
hi
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat tee2.txt
hi
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "good" | tee - -  # 额外重复输出2次
good
good
good
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ echo "good" | tee good.txt > /dev/null
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat good.txt  # 仅输出到文件中
good
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ ls kkk | tee out
ls: cannot access kkk: No such file or directory
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat out  # 正常没有把错误信息输出到文件中
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ ls kkk 2>&1 | tee out
ls: cannot access kkk: No such file or directory
[cindy@iZbp15qc4wmx335c268l5mZ ~]$ cat out  # 此时错误信息有输出到文件中
ls: cannot access kkk: No such file or directory

split

xargs

参考链接

https://www.cnblogs.com/w-j-q/p/14833714.html

https://blog.csdn.net/m0_50370837/article/details/125068528

https://blog.csdn.net/weixin_50196615/article/details/121834020

https://blog.csdn.net/weixin_45842494/article/details/124679008

http://linux.tedu.cn/workplace/420732.html

https://blog.csdn.net/cnds123321/article/details/125150383

https://blog.csdn.net/carefree2005/article/details/115324770

https://www.cnblogs.com/baichunyu/p/15314763.html

https://www.cnblogs.com/nanruosen/p/16317025.html