#Linux Shell 脚本编程(10)—文本过滤(合并与分割—sort、uniq、join、cut、paste、split)

本文介绍Linux下文本处理常用命令,如sort、uniq、cut、join、paste和split等,涵盖基本用法与实例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Linux Shell 脚本编程(10)—文本过滤(合并与分割—sort、uniq、join、cut、paste、split)

文本过滤

sort命令

  • 它将文件进行排序,并将排序结果标准输出。sort命令既可以从特定的文件,也可以从stdin中获取输入。
  • 如果 File 参数指定多个文件,那么 sort 命令将这些文件连接起来,并当作一个文件进行排序。

  • 格式 sort [选项] file(s)

1. 选项

option意义
-b忽略每行前面开始出的空格字符
-c检查文件是否已经按照顺序排序
-ggeneral-numeric-sort —-按照常规数值排序
-i排序时,除了040至176之间的ASCII字符外,忽略其他的字符;
-m将几个排序号的文件进行合并;
-n–numeric-sort 根据字符串数值比较
-M将前面3个字母依照月份的缩写进行排序;
-n依照数值的大小排序;
-o<输出文件>将排序后的结果存入制定的文件;
-r以相反的顺序来排序
-u去重,就是 uniq ,相同的数据中,仅出现一行代表
-t<分隔字符>指定排序时所用的栏位分隔字符,默认是用 [tab] 键来分隔;
-k <数字n> 按照指定的区间 (field)[第n栏数据]来进行排序
+<起始栏位>-<结束栏位>以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。

2. 实例

2.1 默认情况下是按ASCII值进行比较,升序排序输出(将文件/文本的每一行作为一个单位,相互比较,比较原则是从首字符向后进行)

#字符文本
jianliu@ubuntu:~/aa$  cat test0.txt
aaa:10:1.1 
ccc:30:3.3 
eee:50:5.5
ddd:40:4.4 
bbb:20:2.2  
eee:50:5.5

jianliu@ubuntu:~/aa$ sort test0.txt
aaa:10:1.1 
bbb:20:2.2  
ccc:30:3.3 
ddd:40:4.4 
eee:50:5.5
eee:50:5.5

#数字文本( 会出现2比10的情况,因为默认是比较ASCII码,按字符处理)
jianliu@ubuntu:~/aa$ cat test1.txt
23
10
2
345
4
10
23
55

jianliu@ubuntu:~/aa$ sort test1.txt
10
10
2
23
23
345
4
55

2.2 -u, 去重,忽略相同行(与uniq命令类似)

jianliu@ubuntu:~/aa$ sort -u test0.txt
aaa:10:1.1 
bbb:20:2.2  
ccc:30:3.3 
ddd:40:4.4 
eee:50:5.5

jianliu@ubuntu:~/aa$ cat test1.txt | sort -u
10
2
23
345
4
55

jianliu@ubuntu:~/aa$ sort -u < test1.txt
10
2
23
345
4
55

2.3 -n, 按常规数字大小进行排序

jianliu@ubuntu:~/aa$ sort -n test1.txt
2
4
10
10
23
23
55
345

jianliu@ubuntu:~/aa$ sort -nu test1.txt
2
4
10
23
55
345

jianliu@ubuntu:~/aa$ sort -n test0.txt
aaa:10:1.1 
bbb:20:2.2  
ccc:30:3.3 
ddd:40:4.4 
eee:50:5.5
eee:50:5.5

2.3 -r, 以相反的顺序进行排序(倒序)

jianliu@ubuntu:~/aa$ sort -nu -r test1.txt
345
55
23
10
4
2

jianliu@ubuntu:~/aa$ sort -u -r test0.txt
eee:50:5.5
ddd:40:4.4 
ccc:30:3.3 
bbb:20:2.2  
aaa:10:1.1 

2.4 -k 指定排序准则参照的域(对哪个域进行排序,结合-t选项一起使用)

  • -k选项的语法:
# ----Start-------------,--------End--------
 FStart.CStart Modifier, FEnd.CEnd Modifier
  • 分为Start部分和End部分。 Modifier就是n,r,u等选项。
  • Start部分:
    FStart表示使用的起始域(排序的参考)
    CStart 则表示在FStart域中从第几个字符开始算“排序首字符”,即从FStart域的第CStart位作为起点;可以省略,则表示从本域的开头部分开始
  • End部分
    FEnd表示使用的结尾域(排序的参考)
    CEnd则表示在FEnd域中从第几个字符开始算“排序尾字符”,即从FEnd域的第CEnd位作为域2尾;可以省略,则表示结尾到“域尾”,即本域的最后一个字符。 若将CEnd=0,表示结尾到“域尾”

  • (1)对第2个域开始到最后一个域位置的内容进行排序

#该文本有三栏,每一栏数据被:分隔符分开。
jianliu@ubuntu:~/aa$ cat test0.txt
ABC:BB:CC
DFG:30:FF
afe:10:1.1 
cfa:20:3.3 
eea:40:4.5
dck:50:2.4 
bdn:30:3.4  
ecb:40:5.5

#按数值大小进行排序,没有去重
jianliu@ubuntu:~/aa$ sort -n -k 2 -t: test0.txt
ABC:BB:CC
afe:10:1.1 
cfa:20:3.3 
bdn:30:3.4  
DFG:30:FF
ecb:40:5.5
eea:40:4.5
dck:50:2.4 

#按数值大小进行排序,去重
jianliu@ubuntu:~/aa$ sort -un -k 2 -t: test0.txt
ABC:BB:CC
afe:10:1.1 
cfa:20:3.3 
DFG:30:FF
eea:40:4.5
dck:50:2.4 

jianliu@ubuntu:~/aa$ sort  -k 2n -t: test0.txt
ABC:BB:CC
afe:10:1.1 
cfa:20:3.3 
bdn:30:3.4  
DFG:30:FF
ecb:40:5.5
eea:40:4.5
dck:50:2.4 


jianliu@ubuntu:~/aa$ sort -u -k 2n -t: test0.txt
ABC:BB:CC
afe:10:1.1 
cfa:20:3.3 
DFG:30:FF
eea:40:4.5
dck:50:2.4 
  • (2)仅仅对第3个域的内容进行排序,按照数值大小升序。
jianliu@ubuntu:~/aa$ cat test0.txt
ABC:BB:CC
DFG:30:FF
afe:10:1.1 
cfe:20:3.3 
eea:40:4.5
dck:50:2.4 
bdn:30:3.4  
ecb:40:5.5

jianliu@ubuntu:~/aa$ cat test0.txt | sort -t ':' -n -k 3,3
ABC:BB:CC
DFG:30:FF
afe:10:1.1 
dck:50:2.4 
cfe:20:3.3 
bdn:30:3.4  
eea:40:4.5
ecb:40:5.5
  • (3)对第1个域的第2个字符到第一栏的第3个字符进行排序,升序。
jianliu@ubuntu:~/aa$ cat test0.txt
ABC:BB:CC
DFG:30:FF
afe:10:1.1 
cfe:20:3.3 
eea:40:4.5
dck:50:2.4 
bdn:30:3.4  
ecb:40:5.5

jianliu@ubuntu:~/aa$ cat test0.txt | sort -t ':' -k 1.2,1.3
ABC:BB:CC
ecb:40:5.5
dck:50:2.4 
bdn:30:3.4  
eea:40:4.5
afe:10:1.1 
cfe:20:3.3 
DFG:30:FF


#再根据域2进行反序输出
jianliu@ubuntu:~/aa$ cat test0.txt | sort -t ':' -k 1.2,1.3 -k 2r
ABC:BB:CC
ecb:40:5.5
dck:50:2.4 
bdn:30:3.4  
eea:40:4.5
cfe:20:3.3 
afe:10:1.1 
DFG:30:FF

uniq命令

  • uniq命令可以去除排序过后的文件中的重复行,因此经常和sort合用。
  • 为使uniq起作用,所有的重复行必须是相邻的。

1. uniq 语法格式

  • uniq [-icu] (参数)
    • -i : 忽略大小写字符的不同;
    • -c : 进行计数,在每列旁边显示该行重复出现的次数;
    • -u : 只显示唯一的行(不重复的行),即重复的行数据,一个都不显示。
    • -d : 仅显示重复出现的行列;
    • -s<字符位置> : 忽略比较指定的字符
    • -f<栏位> : 忽略比较指定的栏位
    • -w<字符位置> : 指定要比较的字符。

2. 参数

  • 输入文件:指定要去除的重复行文件。如果不指定此项,则从标准读取数据;
  • 输出文件:指定要去除重复行后的内容要写入的输出文件。如果不指定此选项,则将内容显示到标准输出设备(显示终端)。

3. 测试实例

  • 直接对文件进行uniq操作,只会对相邻的重复行进行去重,不处于相邻位置的重复数据行不会被删除!!
jianliu@ubuntu:~/aa$ cat test1.txt
kang dian feng
cao xiao qing
cao xiao qing
zhang yi shang
hello world
zhang jian
hello world

jianliu@ubuntu:~/aa$ uniq test1.txt
kang dian feng
cao xiao qing
zhang yi shang
hello world
zhang jian
hello world
  • 对文件进行排序,再执行uniq
    sort file | uniq 等价于 sort -u file
jianliu@ubuntu:~/aa$ cat test1.txt | sort -r | uniq
zhang yi shang
zhang jian
kang dian feng
hello world
cao xiao qing

 jianliu@ubuntu:~/aa$ sort -ur test1.txt
zhang yi shang
zhang jian
kang dian feng
hello world
cao xiao qing
  • 只显示唯一不重复行
  jianliu@ubuntu:~/aa$ uniq -u test1.txt
kang dian feng
zhang yi shang
hello world
zhang jian
hello world

jianliu@ubuntu:~/aa$ sort test1.txt | uniq -u
kang dian feng
zhang jian
zhang yi shang
  • 统计各行在文件中出现的次数,在行首显示重复的次数
jianliu@ubuntu:~/aa$ sort test1.txt | uniq -c
2 cao xiao qing
2 hello world
1 kang dian feng
1 zhang jian
1 zhang yi shang
  • 在文件中找出重复的行
jianliu@ubuntu:~/aa$ sort test1.txt | uniq -d
cao xiao qing
hello world

cut 命令

1. cut命令说明

  • cut命令用来显示行中的指定部分,删除文件中指定字段
  • cut命令对文本的列(字段)进行操作!!
  • cut经常用来显示文件的内容,类似于type命令。

  • 该命令有两项功能,

    • 用来显示文件的内容,它依次读取由参数file所指明的文件,将它们的内容输出到标准输出上;
    • 其二是连接两个或多个文件,如cut fl f2 >f3将把文件fl和几的内容合并起来,然后通过输出重定向符“>”的作用,将它们放入文件f3中。
  • 一般用more等命令分屏显示。为了控制滚屏,可以按Ctrl+S键,停止滚屏;
    按Ctrl+Q键可以恢复滚屏。按Ctrl+C(中断)键可以终止该命令的执行,并且返回Shell提示符状态。

  • 语法格式

    cut [选项] file

2. 选项

option意义
-b仅显示行中指定直接范围的内容;
-c仅显示行中指定范围的字符(字符区间);
-d指定字段的分隔符,默认的字段分隔符为“TAB”;
-f显示指定字段的内容;依据 -d 的分隔符将一行信息分割成为数段,用 -f n取出第n段数据
-n与“-b”选项连用,不分割多字节字符;
–complement提取指定字节、字符或字段之外的列;
–help显示指令的帮助信息;
–version显示指令的版本信息。

3. 测试实例

3.1 -f,-d 提取指定栏字段内容

jianliu@ubuntu:~/aa$ cat test0.txt
ABC:BB:CC
DFG:30:FF
afe:10:1.1 
cfe:20:3.3 
eea:40:4.5
dck:50:2.4 
bdn:30:3.4  
ecb:40:5.5

#提取第二栏字段数据。分隔符为:
jianliu@ubuntu:~/aa$ cut -d ':' -f 2 test0.txt
BB
30
10
20
40
50
30
40

#提取第2,3栏字段数据
jianliu@ubuntu:~/aa$ cut -d ':' -f 2,3 test0.txtBB:CC
30:FF
10:1.1 
20:3.3 
40:4.5
50:2.4 
30:3.4  
40:5.5

3.2 –complement, 提取指定字段之外的列

#提取第二栏列数据-----
jianliu@ubuntu:~/aa$ cut -d ':' -f2 --complement test0.txt
ABC:CC
DFG:FF
afe:1.1 
cfe:3.3 
eea:4.5
dck:2.4 
bdn:3.4  
ecb:5.5

3.3 -c -b 提取指定字段的字符或者字节区间。

  • cut -d 分隔符 -c 字符区间 file ==>用于排列整齐的信息
  • 字符区间写法

    • (1) N- : 从第N个字节、字符、字段到结尾
    • (2) N-M : 从第N个字节/字符/字段到第M个(包括M在内)字节/字符/字段;
    • (3) -M : 从第1个字节/字符/字段到第M个(包括M在内)字节/字符/字段

    • 范围的类型

    • -b : 字节
    • -c : 字符
    • -f : 定义字段
打印第1——第3个字符
jianliu@ubuntu:~/aa$ cut  -c1-3 test0.txt
ABC
DFG
afe
cfe
eea
dck
bdn
ecb

#打印前4个字符
jianliu@ubuntu:~/aa$ cut -c-4 test0.txt
ABC:
DFG:
afe:
cfe:
eea:
dck:
bdn:
ecb:

#打印从第5个字符开始到结尾
jianliu@ubuntu:~/aa$ cut -c5- test0.txt
BB:CC
30:FF
10:1.1 
20:3.3 
40:4.5
50:2.4 
30:3.4  
40:5.5

join 命令

  • join命令两个文件中,制定栏位内容相同的行连接起来。找出两个文件中,指定栏位内容相同的行,并加以合并,再输出到标准输出设备
  • 语法格式
    join 选项 (file1 file2)

  • 注:这两个文件必须在已经在此列上是依照同样的规则进行了排序。因此
    在使用join前,应先sort排序

1. 选项

-a<12>:除了显示原来的输出内容之外,还显示指令文件中没有相同栏位的行;

-e<字符串>:若[文件1]与[文件2]中找不到指定的栏位,则在输出中填入选项中的字符串;

-i或--ignore-case:比较栏位内容时,忽略大小写的差异; 

-j FIELD :等同于 -1 FIELD -2 FIELD,-j指定一个域作为匹配字段

-o<格式>:按照指定的格式来显示结果;

-t<字符>:使用栏位的分割字符;

-v<12>:更-a相同,但是只显示文件中没有相同栏位的行; 

-1<栏位FIELD>:连接[文件1]指定的栏位; 

-2<栏位FIELD>:连接[文件2]指定的栏位。

2. 实例操作

  • 两个文本文件如下;
jianliu@ubuntu:~/aa$ cat test0.txt
aaa:1:2
bbb:2:3
ccc:3:6
ddd:4:3
eee:5:5

jianliu@ubuntu:~/aa$ cat test1.txt
aaa:2:1
bbb:6:2
ccc:2:3
fff:4:4
ddd:5:4
  • 默认以第一列作为匹配字段,默认以空格(不限格式)作为分隔符。 -t设置分隔符
jianliu@ubuntu:~/aa$ join -t ':' test0.txt test1.txt
aaa:1:2:2:1
bbb:2:3:6:2
ccc:3:6:2:3
join: test1.txt:5: is not sorted: ddd:5:4
  • -j 数字N 指定以两个文件每一行中第N列作为匹配字段
jianliu@ubuntu:~/aa$ join -t ':' -j 1 test0.txt test1.txt
aaa:1:2:2:1
bbb:2:3:6:2
ccc:3:6:2:3
join: test1.txt:5: is not sorted: ddd:5:4

jianliu@ubuntu:~/aa$ join -t ':' -j 2 test0.txt test1.txt
2:bbb:3:aaa:1
join: test1.txt:3: is not sorted: ccc:2:3
  • -1 数字M -2 数字N file1 file2 以file1的第M列和file2的第N列作匹配字段。
jianliu@ubuntu:~/aa$ join -t ':' -1 2 -2 3 test0.txt test1.txt
1:aaa:2:aaa:2
2:bbb:3:bbb:6
3:ccc:6:ccc:2
4:ddd:3:fff:4
4:ddd:3:ddd:5

#最后两行的行首均为4,是因为test0.txt中第4行和test1.txt中的第4、5行均匹配。
  • -o 控制输出格式
jianliu@ubuntu:~/aa$ join -t ':' -o 1.1 -o 1.2 -o 1.3 -o 2.1 -o 2.2 -o 2.3 -e 'empty_' -a 1 test0.txt test1.txt
aaa:1:2:aaa:2:1
bbb:2:3:bbb:6:2
ccc:3:6:ccc:2:3
ddd:4:3:empty_:empty_:empty_
eee:5:5:empty_:empty_:empty_
join: test1.txt:5: is not sorted: ddd:5:4

#-o 指定 将file1的1,2,3列,file2的1,2,3 列都输出。
#-a指定将file1中不匹配的行也输出-e选项指示未匹配的部分使用empty补齐。
  • -v 输出不匹配的行
# -v 1 表示显示file1中的不匹配数据
jianliu@ubuntu:~/aa$ join  -t ':' -j 1 -v 1  test0.txt test1.txt
ddd:4:3
eee:5:5
join: test1.txt:5: is not sorted: ddd:5:4

jianliu@ubuntu:~/aa$ join -t ':' -j 1 -v 2 test0.txt test1.txt
fff:4:4
join: test1.txt:5: is not sorted: ddd:5:4
ddd:5:4
  • 利用管道和字符‘-’将多个文件join到一起
#将多个格式同样的文件join到一起,而join接受的是两个文件的指令,此时我们能够使用管道和字符“-"来实现
join file1 file2 | join - file3 | join - file4 

paste 命令

  • paste命令用于将多个文件按照列(栏)进行合并成一个多列文件,列数为多个文件的列数之和。并按照源多个文件的列顺序进行列栏数据的排列(从左到右排起来)。
  • 参考资料:http://www.cnblogs.com/cyf333333/p/5528689.html

1. 格式及选项

  • paste 选项 file1 file2
  • 选项

    -d<分隔符>或--delimiters=<分隔符>:  用指定的分隔符分割拼接的列,列间分割标志;默认是空格。
    -s或——serial                         串列进行而非平行处理。

2. 实例说明

  • 实例文本
jianliu@ubuntu:~/aa$ cat test0.txt
aaa
bbb
ccc
ddd
eee
fff

jianliu@ubuntu:~/aa$ cat test1.txt
111
222
333
444
555
666
  • 直接进行拼接
jianliu@ubuntu:~/aa$ paste test0.txt test1.txt
aaa 111
bbb 222
ccc 333
ddd 444
eee 555
fff 666
  • -d, 使用指定的分隔符隔开各个文件的列
jianliu@ubuntu:~/aa$ paste -d ':' test0.txt test1.txt
aaa:111
bbb:222
ccc:333
ddd:444
eee:555
fff:666

#-d之后使用双引号和单引号甚至不用引号的结果一样,而且只能指定一个字符,对于-d"::::----"仍然只有第一个字符会被取为分隔符.
  • -s, 删除所有换行,即将所有行合并成一整行。可以用-d指定相邻行数据合并后的分隔符,默认是空格。
    (1) paste file -s
jianliu@ubuntu:~/aa$ paste test0.txt -s
aaa bbb ccc ddd eee fff

jianliu@ubuntu:~/aa$ paste test0.txt -s -d:
aaa:bbb:ccc:ddd:eee:fff

(2)paste file1 file2 -s
每个文件内容变成一行,最终结果为二行,按照文件顺序输出。

jianliu@ubuntu:~/aa$ paste test0.txt test1.txt -s
aaa bbb ccc ddd eee fff
111 222 333 444 555 666

jianliu@ubuntu:~/aa$ paste test0.txt test1.txt -s -d:
aaa:bbb:ccc:ddd:eee:fff
111:222:333:444:555:666

split 命令

  • split命令可以将一个大文件分割成很多个小文件,有时需要将文件分割成更小的片段,比如为提高可读性,生成日志等
  • 参考文献:http://man.linuxde.net/split

1. split命令格式及选项

  • 格式: split 选项 file
  • 选项
-b:  值为每一输出档案的大小,单位为 byte。
-C:  每一输出档中,单行的最大 byte 数。 
-d:  使用数字作为后缀。 
-l:  值为每一输出档的列数大小。

2. 实例测试

  • 测试文件(大小200KB)
jianliu@ubuntu:~/ccc$ dd if=/dev/zero bs=200K count=1 of=date.file
1+0 records in
1+0 records out
204800 bytes (205 kB) copied, 0.000256486 s, 798 MB/s

jianliu@ubuntu:~/ccc$ ls -l
total 200
-rw-rw-r-- 1 jianliu jianliu 204800 Oct 19 07:55 date.file
jianliu@ubuntu:~/ccc$ chmod a+x date.file
jianliu@ubuntu:~/ccc$ ls -l
total 200
-rwxrwxr-x 1 jianliu jianliu 204800 Oct 19 07:55 date.file
  • 将date.file分割成大小为20KB的多个小文件
jianliu@ubuntu:~/ccc$ split -b 20k date.file

jianliu@ubuntu:~/ccc$ ls -l
total 400
-rwxrwxr-x 1 jianliu jianliu 204800 Oct 19 07:55 date.file
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xaa
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xab
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xac
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xad
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xae
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xaf
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xag
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xah
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xai
-rw-rw-r-- 1 jianliu jianliu  20480 Oct 19 07:59 xaj
  • -d, 指定分割的小文件的后缀名称为数字后缀; -a,指定后缀的长度
jianliu@ubuntu:~/ccc$ split -b 20K date.file -d -a 4

jianliu@ubuntu:~/ccc$ ls 
date.file  x0000  x0001  x0002  x0003  x0004  x0005  x0006  x0007  x0008  x0009
  • 指定分割后文件的文件名前缀
date.file   split_0001  split_0003  split_0005  split_0007  split_0009
split_0000  split_0002  split_0004  split_0006  split_0008
  • -l,根据文件的行数来分割文件
#,文件分割成每个包含10行的小文件:
jianliu@ubuntu:~/ccc$ split -l 10 date.file -d -a 4 split_
jianliu@ubuntu:~/ccc$ ls
date.file  split_0000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值