一、转换和删除重复命令——tr
【命令格式】
tr [option] [string1] [string2]
【举例】
1. 字符替换:
> echo "this is a test string."|tr -s "[a-z]" "[A-Z]"
THIS IS A TEST STRING.
#使用重定向、可以实现文本内容的大小写转换
> tr -s "[a-z]" "[A-Z]" < list.txt
#将指定的字母转换成对应的形式
> echo "this is a test string." | tr -s "[test]" "[TEST]"
ThiS iS a TEST STring.
*这里要注意,如果对同一个字母定义两个不同的转换后字符,则以最后一个为准,比如:
> echo "this is a test string." | tr -s "[test]" "[TESf]"
fhiS iS a fESf Sfring.
#替换文本中的特殊符号,比如将##替换为制表符\t
假设存在以下文件:
> cat student2
283214321##Liulu$$0::A**B&&0\\
282351512##Yangrui$$B::C**0&&0\\
283245314##Xuli$$0::0**B&&D\\
293831944##Xiayu$$0::0**0&&0\\
213432143##Heli$$A::0**A&&B\\
279058640##Liyan$$B::B**C&&0\\
> tr -s "##" "\t" < student2
283214321 Liulu$$0::A**B&&0\\
282351512 Yangrui$$B::C**0&&0\\
283245314 Xuli$$0::0**B&&D\\
293831944 Xiayu$$0::0**0&&0\\
213432143 Heli$$A::0**A&&B\\
279058640 Liyan$$B::B**C&&0\\
2. 删除字符:
#删除重复的字符:
> echo "HHHHHHHHeeeeellooooooo" | tr -s "Heo"
Hello
#也可以引用一个字符集去删除重复字符
> echo "HHHHHHHHeeeeellooooooo" | tr -s "[a-z][A-Z]"
Helo
#删除多余的空行:
> cat duplicate.txt
234 2134
321 43221
4321 39875
3212 8549
> tr -s "\n" < duplicate.txt
234 2134
321 43221
4321 39875
3212 8549
或者:
> tr -s "\012" < duplicate.txt
234 2134
321 43221
4321 39875
3212 8549
#删除指定的特殊字符
> echo "my name is suse."| tr -d "msu"
y nae i e.
二、排序命令——sort
sort可以按一个或多个字段排序,还可以合并文件,虽然速度可能不快,但用途较广。
【命令格式】
sort [option] [filename]
【常用选项】
【举例】
指定某一列为排序的主键:
#假设存在上述文件,按照第二列排序:
> sort -k2 list.txt
#以第一列中的第二个字符排序:
> sort -k1.2 list.txt
#也可以在上面的基础上加入n选项,进一步按照数字大小进行排序
> sort -k1.2n list.txt
#指定多个字段进行排序,下面的例子含义是,先按第一列(第二个字符)排序,之后在这个范围内再按第四列排序:
> sort -k1.2,4n list.txt
#也可以写成
> sort -k1.2 -k4n list.txt
#使用cu检查文件是否排序或存在重复行
#使用uf删除重复行并忽略大小写后进行排序
#使用m选项合并文件并排序、之后输出到一个新文件中,被合并的文件列数应该相同
sort -m student2.1 student2.2 > student_sort
*如果是两个很大的文本文件进行合并排序,应该先对每个文件进行排序、再合并,这样可以提升合并的速度
#与其他命令配合使用,比如要查看/etc下最大的五个文件:
> ls -l /etc | awk '{print $1,$5,$9}' | sort -n -k2 | tail -5
三、数据剪切命令——cut
【命令格式】
cut [option] [filename]
*Linux中的cut命令不会改变原有文件的内容,这一点和windows的“剪切”有区别。
#复制list_name.txt文件中每列的前四个字节:
> cut -b-4 list_new.txt
#复制list_name.txt文件中每列第5到第8个字符:
> cut -c5-10 list_new.txt
#复制list_name.txt文件中第1,2,3,5列:
> cut -f1-3,5 list_new.txt
四、数据粘贴命令——paste
paste命令一般和cut配合使用,命令格式如下:
paste [option] [file1,file2...]
【常用选项】
d:对新生成的文本指定新的字段分隔符,默认为Tab
s:将粘贴的内容合并成行,即横向粘贴,默认为纵向
假设存在以下文件:
> cat cut.txt
1234
2234
3234
4234
5234
> cat cut1.txt
aa1
bb2
cc3
aa2
bb3
cc4
#将cut1.txt粘贴到cut.txt后面
> paste cut.txt cut1.txt
1234 aa1
2234 bb2
3234 cc3
4234 aa2
5234 bb3
#将cut.txt粘贴到cut1.txt后面
> paste cut1.txt cut.txt
aa1 1234
bb2 2234
cc3 3234
aa2 4234
bb3 5234
#横向粘贴
> paste -s cut1.txt cut.txt
aa1 bb2 cc3 aa2 bb3 cc4
1234 2234 3234 4234 5234
#指定第一二列用tab分割,第二三列用#分割
> paste -d'\t#' cut.txt cut.txt cut.txt
1234 1234#1234
2234 2234#2234
3234 3234#3234
4234 4234#4234
5234 5234#5234
#假设存在文件serialNum,用-表示来自管道的文件,如果想把serialNum放到后面,只需把它与-交换位置即可:
> cat serialNum
1
2
3
4
5
> cat cut.txt | paste -d"#" serialNum -
1#1234
2#2234
3#3234
4#4234
5#5234
*不同的Shell可能会把同一行按照不同的分隔符分割(比如tab后面有空格,则被当做两列),注意反复调试
五、数据连接命令——join
这个命令与数据库里的join意义类似,将两个具有相同列的文件,通过这个相同列进行关联后输出结果
【命令格式】
join [option] file1 file2
【常用选项】
上面这句话需要解释一下:join允许在参数后面加数字1、表示文件1的参数,加数字2表示文件2的参数
假设存在以下两个文件:
> cat join1.txt
1 1234 33 56 23
2 2234 46 43 98
3 3234 97 34 56
4 4234 85 33 57
5 5234 43 98 87
6 6234 87 45 13
7
> cat join2.txt
1 aa1 1234
2 bb2 2234
3 cc3 3234
4 aa2 4234
5 bb3 5234
aa3 6234
#直接将join1.txt和join2.txt关联:
> join join1.txt join2.txt
1 1234 33 56 23 aa1 1234
2 2234 46 43 98 bb2 2234
3 3234 97 34 56 cc3 3234
4 4234 85 33 57 aa2 4234
5 5234 43 98 87 bb3 5234
可以看出,这样只能输出有关联的行。
#使用参数a1,a2输出两个文件中的无关联行:
> join -a1 -a2 join1.txt join2.txt
1 1234 33 56 23 aa1 1234
2 2234 46 43 98 bb2 2234
3 3234 97 34 56 cc3 3234
4 4234 85 33 57 aa2 4234
5 5234 43 98 87 bb3 5234
6 6234 87 45 13
7
aa3 6234
#使用v1,v2只显示没有关联的行:
> join -v1 -v2 join1.txt join2.txt
6 6234 87 45 13
7
aa3 6234
#使用o选项,只输出join1.txt中的2,3,4,5列和join2.txt中的第2列,之后使用awk命令输出规范化文本、并统计join1.txt中的3,4,5列的总和与平均值
> join -o "2.2,1.2,1.3,1.4,1.5" join1.txt join2.txt|awk '{printf "%-15s %-10s %d %d %d %d %d\n",$1,$2,$3,$4,$5,($3+$4+$5),($3+$4+$5)/3}'
aa1 1234 33 56 23 112 37
bb2 2234 46 43 98 187 62
cc3 3234 97 34 56 187 62
aa2 4234 85 33 57 175 58
bb3 5234 43 98 87 228 76
#如果关联列不在第一行,就需要使用选项“j”指定要关联的列,比如上面两个文件要通过第二、三列进行关联,然后输出第7,1,3,4,5列和3,4,5列的和与平均值
> join -j1 2 -j2 3 join1.txt join2.txt | awk '{printf "%-15s %-10s %d %d %d %d %d\n",$7,$1,$3,$4,$5,($3+$4+$5),($3+$4+$5)/3}'
join: file 1 is not in sorted order
aa1 1234 33 56 23 112 37
bb2 2234 46 43 98 187 62
cc3 3234 97 34 56 187 62
aa2 4234 85 33 57 175 58
bb3 5234 43 98 87 228 76
*如果两个要连接的文件主键没有排序,则在执行join命令时就会报错:join: file 1 is not in sorted order;因此,保险起见,在执行join之前最好把文件按照要关联的列排序一下
#使用选用t指定特定的分隔符分割文件并连接
> cat join1#.txt
1#1234#33#56#23
2#2234#46#43#98
3#3234#97#34#56
4#4234#85#33#57
5#5234#43#98#87
6#6234#87#45#13
7
> cat join2#.txt
1#aa1#1234
2#bb2#2234
3#cc3#3234
4#aa2#4234
5#bb3#5234
#aa3#6234
> join -t"#" join1#.txt join2#.txt
1#1234#33#56#23#aa1#1234
2#2234#46#43#98#bb2#2234
3#3234#97#34#56#cc3#3234
4#4234#85#33#57#aa2#4234
5#5234#43#98#87#bb3#5234
#假如两个文件中某些行的关联列值不同或为空,可以使用-e选项填充这些行使其保留下来进一步进行补齐操作,比如要将join1.txt和join2.txt文件的所有行都关联显示出来,对应不上的列使用#号填充:
> join -e "#" -a1 -a2 -o "1.1,1.2,1.3,1.4,1.5,2.1,2.2,2.3" join1.txt join2.txt
1 1234 33 56 23 1 aa1 1234
2 2234 46 43 98 2 bb2 2234
3 3234 97 34 56 3 cc3 3234
4 4234 85 33 57 4 aa2 4234
5 5234 43 98 87 5 bb3 5234
# # # # # # # #
6 6234 87 45 13 # # #
7 # # # # # # #
# # # # # aa3 6234 #
*注意:使用e选项进行填充时,必须搭配o和a选项使用,否则join命令找不到要填充的位置。
六、去重复命令——uniq
【命令格式】
uniq [option] [input[output]]
【举例】
#假设存在如下文件
> cat uniq1.log
asdf1 aaAA
asdf2 aaAA
asdf3 aabb
asdf3 aabb
asdf5 AABB
asdf4 BBcc
asdf6 BBcc
asdf6 bbCC
asdf6 bbCC
asdf6 BBCC
asdf6 BBcc
asdf6 BBcc
#使用c和d输出重复的行并统计重复次数:
> sort uniq1.log | uniq -cd
2 asdf3 aabb
2 asdf6 bbCC
3 asdf6 BBcc
*之所以要先排序,是因为uniq只会统计连续重复的行,否则就会出现如下统计结果:
> uniq -cd uniq1.log
2 asdf3 aabb
2 asdf6 bbCC
2 asdf6 BBcc
#使用f选项忽略第一个字段,然后使用s3从第2个字段的第三个字符开始对比:
> sort -k2 uniq1.log | uniq -f1 -s3
asdf1 aaAA
asdf3 aabb
asdf5 AABB
asdf6 bbCC
asdf4 BBcc
asdf6 BBCC
七、分割文件命令——split
顾名思义,将大文本文件按照一定规则分割为若干个小文件。
【文件格式】
split [option] [input file] [output file]
【常用选项】
l:按行对文件进行分割
b:按字节对文件进行分割
C:按字节对文件进行分割,split会尽量保持一个整行
d:使用数字作为输出文件的后缀
在指定输出文件名称后,split会将输出文件以指定名称为前缀、在其后加上诸如aa,ab之类的后缀作为分割后的文件名
【举例】
假设存在如下文件,共25行:
> cat list.txt
1234 aa1 23 32 65
2234 bb2 23 34 66
3234 cc3 24 36 67
4234 aa2 25 38 68
5234 bb3 26 40 69
6234 cc4 27 42 70
7234 aa3 28 44 71
8234 bb4 29 46 72
9234 cc5 30 48 73
1567 aa4 31 50 74
2567 bb5 32 52 75
3567 cc6 33 54 76
4567 aa5 34 56 77
5567 bb6 35 58 78
6567 cc7 36 60 79
7567 aa6 37 62 80
8567 bb7 38 64 81
9567 cc8 39 66 82
1790 aa7 40 68 83
2790 bb8 41 70 84
3790 cc9 42 72 85
4790 aa8 43 74 86
5790 bb9 44 76 87
6790 cc1 45 78 88
7790 aa9 46 80 89
#将其按照每7行分割一次的办法进行分割:
> split -l 7 list.txt list
> ls
total 20
-rw-r--r-- 1 xingkai users 126 Nov 28 11:00 listaa
-rw-r--r-- 1 xingkai users 126 Nov 28 11:00 listab
-rw-r--r-- 1 xingkai users 126 Nov 28 11:00 listac
-rw-r--r-- 1 xingkai users 72 Nov 28 11:00 listad
-rw-r--r-- 1 xingkai users 450 Nov 28 10:52 list.txt
linux-gwl8 a1/split> wc -l lista*
7 listaa
7 listab
7 listac
4 listad
25 total
#按文件大小(字节)分割,将上述文件分割为若干个100B的小文件:
> split -b 100 list.txt list
> ls
total 24
-rw-r--r-- 1 xingkai users 100 Nov 28 11:01 listaa
-rw-r--r-- 1 xingkai users 100 Nov 28 11:01 listab
-rw-r--r-- 1 xingkai users 100 Nov 28 11:01 listac
-rw-r--r-- 1 xingkai users 100 Nov 28 11:01 listad
-rw-r--r-- 1 xingkai users 50 Nov 28 11:01 listae
-rw-r--r-- 1 xingkai users 450 Nov 28 10:52 list.txt
> wc -l lista
> wc -l lista*
5 listaa
6 listab
5 listac
6 listad
3 listae
25 total