《Linux命令、编辑器与Shell编程》读书笔记4.3-其他数据文件处理命令(tr,sort,cut,paste,join,uniq,split)

来源:互联网 发布:淘宝o2o平台 编辑:程序博客网 时间:2024/04/30 21:34

一、转换和删除重复命令——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 student2283214321##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" < student2283214321       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.txt12342234323442345234> cat cut1.txtaa1bb2cc3aa2bb3cc4

#将cut1.txt粘贴到cut.txt后面

> paste cut.txt cut1.txt1234  aa12234  bb23234  cc34234  aa25234  bb3

#将cut.txt粘贴到cut1.txt后面

> paste cut1.txt cut.txtaa1 1234bb2 2234cc3 3234aa2 4234bb3 5234

#横向粘贴

> paste -s cut1.txt cut.txtaa1  bb2 cc3    aa2     bb3    cc41234 2234   3234        4234   5234
#指定第一二列用tab分割,第二三列用#分割

> paste -d'\t#' cut.txt cut.txt cut.txt1234 1234#12342234 2234#22343234 3234#32344234 4234#42345234 5234#5234

#假设存在文件serialNum,用-表示来自管道的文件,如果想把serialNum放到后面,只需把它与-交换位置即可:

> cat serialNum12345> cat cut.txt | paste -d"#" serialNum -1#12342#22343#32344#42345#5234

*不同的Shell可能会把同一行按照不同的分隔符分割(比如tab后面有空格,则被当做两列),注意反复调试


五、数据连接命令——join

这个命令与数据库里的join意义类似,将两个具有相同列的文件,通过这个相同列进行关联后输出结果

【命令格式】

join [option] file1 file2

【常用选项】


上面这句话需要解释一下:join允许在参数后面加数字1、表示文件1的参数,加数字2表示文件2的参数

假设存在以下两个文件:

> cat join1.txt1       1234    33      56      232       2234    46      43      983       3234    97      34      564       4234    85      33      575       5234    43      98      876       6234    87      45      137> cat join2.txt1       aa1     12342       bb2     22343       cc3     32344       aa2     42345       bb3     5234        aa3     6234

#直接将join1.txt和join2.txt关联:

> join join1.txt join2.txt1 1234 33 56 23 aa1 12342 2234 46 43 98 bb2 22343 3234 97 34 56 cc3 32344 4234 85 33 57 aa2 42345 5234 43 98 87 bb3 5234
可以看出,这样只能输出有关联的行。

#使用参数a1,a2输出两个文件中的无关联行:

> join -a1 -a2 join1.txt join2.txt1 1234 33 56 23 aa1 12342 2234 46 43 98 bb2 22343 3234 97 34 56 cc3 32344 4234 85 33 57 aa2 42345 5234 43 98 87 bb3 52346 6234 87 45 137aa3 6234
#使用v1,v2只显示没有关联的行:

> join -v1 -v2 join1.txt join2.txt6 6234 87 45 137aa3 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 37bb2             2234       46 43 98 187 62cc3             3234       97 34 56 187 62aa2             4234       85 33 57 175 58bb3             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 orderaa1             1234       33 56 23 112 37bb2             2234       46 43 98 187 62cc3             3234       97 34 56 187 62aa2             4234       85 33 57 175 58bb3             5234       43 98 87 228 76

*如果两个要连接的文件主键没有排序,则在执行join命令时就会报错:join: file 1 is not in sorted order;因此,保险起见,在执行join之前最好把文件按照要关联的列排序一下

#使用选用t指定特定的分隔符分割文件并连接

> cat join1#.txt1#1234#33#56#232#2234#46#43#983#3234#97#34#564#4234#85#33#575#5234#43#98#876#6234#87#45#137> cat join2#.txt1#aa1#12342#bb2#22343#cc3#32344#aa2#42345#bb3#5234#aa3#6234> join -t"#" join1#.txt join2#.txt1#1234#33#56#23#aa1#12342#2234#46#43#98#bb2#22343#3234#97#34#56#cc3#32344#4234#85#33#57#aa2#42345#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.txt1 1234 33 56 23 1 aa1 12342 2234 46 43 98 2 bb2 22343 3234 97 34 56 3 cc3 32344 4234 85 33 57 4 aa2 42345 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.logasdf1   aaAAasdf2   aaAAasdf3   aabbasdf3   aabbasdf5   AABBasdf4   BBccasdf6   BBccasdf6   bbCCasdf6   bbCCasdf6   BBCCasdf6   BBccasdf6   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 -s3asdf1   aaAAasdf3   aabbasdf5   AABBasdf6   bbCCasdf4   BBccasdf6   BBCC


七、分割文件命令——split

顾名思义,将大文本文件按照一定规则分割为若干个小文件。

【文件格式】

split [option] [input file] [output file]

【常用选项】

l:按行对文件进行分割

b:按字节对文件进行分割

C:按字节对文件进行分割,split会尽量保持一个整行

d:使用数字作为输出文件的后缀

在指定输出文件名称后,split会将输出文件以指定名称为前缀、在其后加上诸如aa,ab之类的后缀作为分割后的文件名

【举例】

假设存在如下文件,共25行:

> cat list.txt1234    aa1     23      32      652234    bb2     23      34      663234    cc3     24      36      674234    aa2     25      38      685234    bb3     26      40      696234    cc4     27      42      707234    aa3     28      44      718234    bb4     29      46      729234    cc5     30      48      731567    aa4     31      50      742567    bb5     32      52      753567    cc6     33      54      764567    aa5     34      56      775567    bb6     35      58      786567    cc7     36      60      797567    aa6     37      62      808567    bb7     38      64      819567    cc8     39      66      821790    aa7     40      68      832790    bb8     41      70      843790    cc9     42      72      854790    aa8     43      74      865790    bb9     44      76      876790    cc1     45      78      887790    aa9     46      80      89

#将其按照每7行分割一次的办法进行分割:

> split -l 7 list.txt list> lstotal 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.txtlinux-gwl8 a1/split> wc -l lista*  7 listaa  7 listab  7 listac  4 listad 25 total

#按文件大小(字节)分割,将上述文件分割为若干个100B的小文件:

> split -b 100 list.txt list> lstotal 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



0 0