目录

wc,cut,sort,uniq,tr,paste,split


1、文本统计wc

wc  [OPTION]... [FILE]...

      不指定选项默认:输出每个指定文件的行数、单词数和字节数如果指定了多于一个文件,继续给出所有相关数据的总计。如果没有指定文件,或者文件为"-",则从标准输入读取数据。

   -l, --lines        输出行数统计 

  -w, --words             统计单词数

  -c, --bytes输出字节数统计

  -m, --chars输出字符数统计

[root@Node3 src]# cat test1
aaa  bbb  ccc               #空格和换行符也都算1个字符
                       
hello world
你好,世界                #中文1个算多个字符,没有中文时,字符数等于字节数
[root@Node3 src]# wc test1
 4  6 43 test1
[root@Node3 src]# wc -l test1
4 test1
[root@Node3 src]# wc -m test1
33 test1
[root@Node3 src]# wc -c test1
43 test1


[root@Node3 src]# wc test1
 3  4 25 test1
[root@Node3 src]# wc -l test1
3 test1
[root@Node3 src]# wc -w test1
4 test1
[root@Node3 src]# wc -c test1
25 test1
[root@Node3 src]# wc -m test1
25 test1

2、字符截取:cut

      从每个文件中输出指定部分到标准输出,它每次处理的对象是“一行”文本,从中选取出用户所需要的部分,返回的是列默认以空格为分隔符,也可以指定特定的分隔符,然后打印出以分隔符隔开的集体某一列或某几列。

cut  [OPTION] ... [FILE]..

    -d:--delimiter=分界符   使用指定分界符代替制表符作为区域分界

              -d ' ' :表示以空格为分隔符    #默认以制表符为分割符

    -f #:指明要保留的字段(列)

             单个: #

             离散的多个:#,#,#

             连续的多个:#-#

   -s, --only-delimited     不打印没有包含分界符的行

[root@Node3 src]# cut -f 1 test1
aaa bbb ccc

hello,world
[root@Node3 src]# cut -d '' -f 1 test1
aaa bbb ccc

hello,world
[root@Node3 src]# cut -d ' ' -f 1 test1
aaa

hello,world
[root@Node3 src]# cut -s -d ' ' -f 1 test1
aaa
[root@Node3 src]# cut -d ' ' -f 2 test1
bbb

hello,world
[root@Node3 src]# cut -d ' ' -f 3 test1
ccc

hello,world
[root@Node3 src]# cut -d ' ' -f 4 test1


hello,world
[root@Node3 src]# cut -d ' ' -f 1,3 test1 #保留第一和第三列
aaa ccc

hello,world
[root@Node3 src]# cut -d ' ' -f 1-3 test1 #保留第一到第三列
aaa bbb ccc

hello,world


[root@Node3 src]# cat test2
a	b	c d  e           #一个tab键是制表符,c和d之间是1个空格,d和e之间2个空格

1	2	3 4  5
[root@Node3 src]# cut -f 1 test2   #默认以制表符为分隔符
a

1
[root@Node3 src]# cut -f 3 test2   #制表符和空格有区别
c d  e

3 4  5
[root@Node3 src]# cut -d '' -f 3 test2 #引号之间不能没有空格
a	b	c d  e

1	2	3 4  5
[root@Node3 src]# cut -d ' ' -f 1 test2  #再次说明制表符不等于4个空格
a	b	c

1	2	3
[root@Node3 src]# cut -d '  ' -f 1 test2 #不能以2个空格作为分隔符,必须是单个字符
cut: 分界符必须是单个字符
请尝试执行"cut --help"来获取更多信息。
[root@Node3 src]# cut -d ' ' -f 2 test2
d

4
[root@Node3 src]# cut -d ' ' -f 3 test2 #有多个空格时,以1个空格为分隔符后的列还是1个空格,所有分隔符是多个空格时,使用cut可能会有问题


[root@Node3 src]# cut -d ":" -f 1,6-7 /etc/passwd  #以“:”为分隔符
root:/root:/bin/bash
bin:/bin:/sbin/nologin
daemon:/sbin:/sbin/nologin


[root@Node3 src]# cut -d ' ' -f 4 test2 #下一列
e

5
[root@Node3 src]# echo "1aa2aa3"|cut -d 'a' -f 1
1
[root@Node3 src]# echo "1aa2aa3"|cut -d 'a' -f 2

[root@Node3 src]# echo "1aa2aa3"|cut -d 'a' -f 3
2

  以上cut使用场景是在处理的行中有特定的分隔符的时候,但是如果要处理的行是没有分隔符的,那cut就没有用了吗?

    cut还可以打印指定个数的字符或字节,这个时候cut的用法如下:

[root@Node3 src]# cut -b 5 test1
b

o
[root@Node3 src]# cut -b 5 test1 test2
b

o
c

3
[root@Node3 src]# cut -b 5-10 test1 test2
bbb cc

o,worl
c d  e

3 4  5
[root@Node3 src]# cut -c 5-10 test1 test2
bbb cc

o,worl
c d  e

3 4  5
[root@Node3 src]# cut -c 5-100 test1 test2
bbb ccc

o,world
c d  e

3 4  5

3、文本排序:sort

串联排序所有指定文件并将结果写到标准输出

注意:这里说的排序是行的上,下排序;针对的行不是列

sort [OPTION]... [FILE]...

     -r:逆序排序

     -f:忽略大小写  常与-u结合使用

     -n:按数值大小排序

     -t:指定分隔符,默认是空格

     -k:按照指定的字段范围

     -u:移除重复的行

sort将文件的每一行作为一个单位,相互比较,比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。

1 )准备素材

[root@Node3 src]# cat facebook.txt 
google 110 5000
baidu 100 5000
gab 200 200
guge 50 3000
sohu 100 4500
[root@Node3 src]# sort facebook.txt 
baidu 100 5000
gab 200 200
google 110 5000
guge 50 3000
sohu 100 4500
[root@Node3 src]# sort -n facebook.txt 
baidu 100 5000
gab 200 200
google 110 5000
guge 50 3000
sohu 100 4500
[root@Node3 src]# sort -r facebook.txt 
sohu 100 4500
guge 50 3000
google 110 5000
gab 200 200
baidu 100 5000

第一个域是公司名称,第二个域是公司人数,第三个域是员工平均工资。

2 )我想让facebook.txt按照公司人数排序

[root@Node3 src]# sort -t ' ' -k 2 -n  facebook.txt 
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
gab 200 200

但是,此处出现了问题,那就是baidu和sohu的公司人数相同,都是100人,这个时候怎么办呢?

按照默认规矩,是从第一个域开始进行升序排序,因此baidu排在了sohu前面。

但是这里如果不加-n:

[root@Node3 src]# sort  -t ' ' -k 2 facebook.txt 
sohu 100 4500
baidu 100 5000
google 110 5000
gab 200 200
guge 50 3000

3 )我想让facebook.txt按照公司人数排序 ,人数相同的按照员工平均工资升序排序:

[root@Node3 src]# sort -n -t ' ' -k 2 -k 3 facebook.txt 
guge 50 3000
sohu 100 4500
baidu 100 5000
google 110 5000
gab 200 200

看,我们加了一个-k2 -k3就解决了问题。对滴,sort支持这种设定,就是说设定域排序的优先级,先以第2个域进行排序,如果相同,再以第3个域进行排序

[root@Node3 src]# sort -n -t ' ' -k 2 -k 1 facebook.txt 
guge 50 3000
baidu 100 5000
sohu 100 4500
google 110 5000
gab 200 200

4 )我想让facebook.txt按照员工工资降序排序,如果员工人数相同的,则按照公司人数升序排序

[root@Node3 src]# sort -n -t ' ' -k 3 -r -k 2 facebook.txt 
google 110 5000
baidu 100 5000
sohu 100 4500
guge 50 3000
gab 200 200

[root@Node3 src]# sort -n -t ' ' -k 3r -k 2 facebook.txt #r和区域写在一起
baidu 100 5000
google 110 5000
sohu 100 4500
guge 50 3000
gab 200 200

5 )-k选项的具体语法格式

       要继续往下深入的话,就不得不来点理论知识。你需要了解-k选项的语法格式,如下:

[ FStart [ .CStart ] ] [ Modifier ] [ , [ FEnd [ .CEnd ] ][ Modifier ] ]

这个语法格式可以被其中的逗号(“,”)分为两大部分,Start部分和End部分,注意:Start和End跨域没有意义

先给你灌输一个思想,那就是“如果不设定End部分,那么就认为End被设定为行尾”。这个概念很重要的,但往往你不会重视它。

Start部分也由三部分组成,其中的Modifier部分就是我们之前说过的类似n和r的选项部分。我们重点说说Start部分的FStart和C.Start。

C.Start也是可以省略的,省略的话就表示从本域的开头部分开始。之前例子中的-k 2和-k 3就是省略了C.Start的例子喽。

FStart.CStart,其中FStart就是表示使用的域,而CStart则表示在FStart域中从第几个字符开始算“排序首字符”。

同理,在End部分中,你可以设定FEnd.CEnd,如果你省略.CEnd,则表示结尾到“域尾直到行尾”,即本域的最后一个字符。或者,如果你将CEnd设定为0(零),也是表示结尾到“域尾”。

6)从公司英文名称的第二个字母开始进行排序:

[root@Node3 src]# cat facebook.txt 
google 110 5000
baidu 100 5000
gab 200 200
guge 50 3000
sohu 100 4500
[root@Node3 src]# sort -t ' ' -k 1.2 facebook.txt 
gab 200 200
baidu 100 5000
sohu 100 4500
google 110 5000
guge 50 3000

         看,我们使用了-k 1.2,这就表示对第一个域的第二个字符开始到本域的最后一个字符为止的字符串进行排序。你会发现baidu因为第二个字母是a而名列榜首。sohu和 google第二个字符都是o,但sohu的h在google的o前面,所以两者分别排在第二和第三。guge只能屈居第四了。

[root@xxj tmp]# sort -t' ' -k1.2 555test 
faidu 100 5000
cb aa 30 c
bb aa 30 x
ab ba 30 b
sohu 100 4500
eoogle 100 6000
guge 50 3000
[root@xxj tmp]# sort -nt' ' -k1.2 555test 
ab ba 30 b
bb aa 30 x
cb aa 30 c
eoogle 100 6000
faidu 100 5000
guge 50 3000
sohu 100 4500
[root@xxj tmp]#

只针对公司英文名称的第二个字母进行排序,如果相同的按照员工工资进行降序排序:

[root@Node3 src]# sort -t ' ' -k 1.2,1.2 -k 3,3nr facebook.txt 
baidu 100 5000
gab 200 200
google 110 5000
sohu 100 4500
guge 50 3000

         由于只对第二个字母进行排序,所以我们使用了-k 1.2,1.2的表示方式,表示我们“只”对第二个字母进行排序。(如果你问“我使用-k 1.2怎么不行?”,当然不行,因为你省略了End部分,这就意味着你将对从第二个字母起到本域最后一个字符为止的字符串进行排序)。对于员工工资进行排 序,我们也使用了-k 3,3,这是最准确的表述,表示我们“只”对本域进行排序,因为如果你省略了后面的3,就变成了我们“对第3个域开始到最后一个域位置的内容进行排序” 了。


4、去重复行:uniq

uniq [选项]... [文件]

    说明:这个命令读取输入文件,并比较相邻的行,删除相同且相邻的的重复行

     -i:忽略大小写

     -d:仅显示重复的行

     -u:仅显示不重复的行

     -c:去重后显示每行出现了的次数(相同且相邻才是重复)

[root@Node3 src]# cat uniq.txt 
abc 
123
123
abc
ABC
123
[root@Node3 src]# uniq uniq.txt 
abc 
123
abc
ABC
123
[root@Node3 src]# uniq -i uniq.txt 
abc 
123
abc
123
[root@Node3 src]# uniq -d uniq.txt 
123
[root@Node3 src]# uniq -di uniq.txt 
123
abc
[root@Node3 src]# uniq -u uniq.txt 
abc 
abc
ABC
123
[root@Node3 src]# uniq -c uniq.txt 
      1 abc 
      2 123
      1 abc
      1 ABC
      1 123

  因为uniq是删除去除连续相同的行,所有uniq一般和sort命令一起使用,也就是先将文件使用sort排序(这样重复的内容就能显示在连续的几行中),然后再使用uniq删除掉重复的行

[root@Node3 src]# sort uniq.txt|uniq -c
      3 123
      2 abc
      1 ABC

5、文本替换:tr

tr [OPTION]... SET1 [SET2]  #后面不能带参数

       把输出数据中的在SET1中的每个字符对应地替换为SET2的每个字符

  -d, --delete  删除匹配SET1的内容,并不作替换

[root@localhost ~]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m

[root@localhost ~]# tr 'aen' 'x' </etc/issue      #不会对原文件的内容有影响
CxxtOS rxlxxsx 6.5 (Fixxl)
Kxrxxl \r ox xx \m

[root@localhost ~]# tr 'aen' 'xxx' </etc/issue   #逐字符,不是单词
CxxtOS rxlxxsx 6.5 (Fixxl)
Kxrxxl \r ox xx \m

[root@Node3 src]# echo "xiejun"|tr [xj] [JX]
JieXun
[root@Node3 src]# echo "xiejun"|tr xj JX
JieXun

[root@localhost ~]# tr 'aen' 'xyz' </etc/issue  
CyztOS rylyxsy 6.5 (Fizxl)
Kyrzyl \r oz xz \m

[root@localhost ~]# tr 'aen' '' </etc/issue   
tr: 当不截断设置1 时,字符串2 不能为空
[root@localhost ~]# tr 'aen' ' ' </etc/issue
C  tOS r l  s  6.5 (Fi  l)
K r  l \r o     \m


[root@localhost ~]# tr 'aen'  </etc/issue   
tr: "aen" 后缺少操作数
当进行替换操作时必须给定两组字符串。
请尝试执行"tr --help"来获取更多信息。

root@localhost ~]# tr -d [ae] </etc/issue  
CntOS rls 6.5 (Finl)
Krnl \r on n \m

6、文本合并:paste

  paste的作用在于将文件按照行进行合并,中间使用tab隔开

   -d:指定在合并文件时行间的分隔符,默认是制表符

   -s, --serial  不使用平行的行目输出模式,而是每个文件占用一行

[root@Node3 src]# cat a
1 1
2 2
[root@Node3 src]# cat b
a a
b b
[root@Node3 src]# paste a b
1 1	a a
2 2	b b
[root@Node3 src]# paste -s a b
1 1	2 2
a a	b b
[root@Node3 src]# paste b a
a a	1 1
b b	2 2
[root@Node3 src]# paste -d ':' a b
1 1:a a
2 2:b b
[root@Node3 src]# paste -s -d : a b
1 1:2 2
a a:b b
[root@Node3 src]# cat 1.txt 
1
10
11
1000
19
a
ab
A
b
z
2
5
[root@Node3 src]# cat 1.txt |paste -s
1	10	11	1000	19	a	ab	A	b	z	2	5
[root@Node3 src]# cat 1.txt |paste -s -d :
1:10:11:1000:19:a:ab:A:b:z:2:5
[root@Node3 src]# cat 1.txt |paste -s -d ' '
1 10 11 1000 19 a ab A b z 2 5
[root@Node3 src]# paste a b 1.txt 
1 1	a a	1
2 2	b b	10
		11
		1000
		19
		a
		ab
		A
		b
		z
		2
		5
[root@Node3 src]# paste -s a b 1.txt 
1 1	2 2
a a	b b
1	10	11	1000	19	a	ab	A	b	z	2	5
[root@Node3 src]#

7、分割文件:split

实现文件分割

支持按照行数分割和按照大小分割两种模式

-l:按行分割

-h:按大小分割,

注意:二进制文件没有行的概念,只能按大小进行分割

[root@Node3 src]# cp /etc/passwd .
[root@Node3 src]# cat -n passwd 
     1	root:x:0:0:root:/root:/bin/bash
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
    11	operator:x:11:0:operator:/root:/sbin/nologin
    12	games:x:12:100:games:/usr/games:/sbin/nologin
    13	gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
    14	ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    15	nobody:x:99:99:Nobody:/:/sbin/nologin
    16	dbus:x:81:81:System message bus:/:/sbin/nologin
    17	vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
    18	saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
    19	postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    20	haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
    21	sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin

[root@Node3 src]# split -l 10 passwd passwd_
[root@Node3 src]# ls 
1.txt  a  c             passwd     passwd_ab  sort.txt  test2
2.txt  b  facebook.txt  passwd_aa  passwd_ac  test1     uniq.txt

分隔完成后会生成多个以passwd_开头为文件名的小文件

[root@Node3 src]# cat -n passwd_*
     1	root:x:0:0:root:/root:/bin/bash
     2	bin:x:1:1:bin:/bin:/sbin/nologin
     3	daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4	adm:x:3:4:adm:/var/adm:/sbin/nologin
     5	lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6	sync:x:5:0:sync:/sbin:/bin/sync
     7	shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8	halt:x:7:0:halt:/sbin:/sbin/halt
     9	mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10	uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
    11	operator:x:11:0:operator:/root:/sbin/nologin
    12	games:x:12:100:games:/usr/games:/sbin/nologin
    13	gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
    14	ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
    15	nobody:x:99:99:Nobody:/:/sbin/nologin
    16	dbus:x:81:81:System message bus:/:/sbin/nologin
    17	vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
    18	saslauth:x:499:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
    19	postfix:x:89:89::/var/spool/postfix:/sbin/nologin
    20	haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
    21	sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
    
    
[root@Node3 ~]# ls -lh mariadb-10.1.16-linux-x86_64.tar.gz 
-rw-r--r-- 1 root root 332M 11月 18 17:45 mariadb-10.1.16-linux-x86_64.tar.gz
[root@Node3 ~]# split -b 100M mariadb-10.1.16-linux-x86_64.tar.gz mariadb_
[root@Node3 ~]# ls -lh mariadb_*
-rw-r--r-- 1 root root 100M 11月 26 15:11 mariadb_aa
-rw-r--r-- 1 root root 100M 11月 26 15:11 mariadb_ab
-rw-r--r-- 1 root root 100M 11月 26 15:11 mariadb_ac
-rw-r--r-- 1 root root  32M 11月 26 15:11 mariadb_ad


split

可以将一个大文件分割成很多个小文件,有时需要将文件分割成更小的片段,比如为提高可读性,生成日志

语法

split(选项)(file)PREFIX

选项

-b:值为每一输出档案的大小,单位默认为 -C:每一输出档中,单行的最大 --l:值为每一输出档的列数大小。

PREFIX:代表前导符,可作为切割后文件名的前导符。


实例

生成一个大小为100KB的测试文件:

dd if=/dev/zero bs=100k count=1 of=date.file
结果:
1+0 records in
1+0 records out
102400 bytes (102 kB) copied, 0.00043 seconds, 238 MB/s

使用split命令将上面创建的date.file文件分割成大小为10KB的小文件:

split -b 10k date.file

ls
结果:
date.file xaa xab xac xad xae xaf xag xah xai xaj

文件被分割成多个带有字母的后缀文件,如果想用数字后缀可使用-d参数,同时可以使用-a length来指定后缀的长度:

split -b 10k date.file -d -a 3

 ls
结果:
date.file x000 x001 x002 x003 x004 x005 x006 x007 x008 x009

 

为分割后的文件指定文件名的前缀:

split -b 10k date.file -d -a 3 split_file

 ls
结果:
date.file split_file000 split_file001 split_file002 split_file003 split_file004 split_file005 split_file006 split_file007 split_file008 split_file009

使用-l选项根据文件的行数来分割文件,例如把文件分割成每个包含10行的小文件:

split -l 10 date.file

PS

 cat x*>>y*

 
 将split分割的文件合并成一个