bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
1.1 簡介
tr主要用於將從標准輸入讀取的數據進行結果集映射、字符壓縮和字符刪除。它首先會將讀取的標准輸入進行排序然后按照某種方式換行,然后再根據給出的命令行參數做相關處理。
tr [options] [SET1] [SET2]
-c
:使用SET1的補集-d
:刪除字符-s
:壓縮字符-t
:截斷SET1,使得SET1的長度和SET2的長度相同
1.2 tr映射
如果同時指定了SET1和SET2,則是將SET1的符號按位置一一對應映射為SET2中的符號。換句話說,就是對應替換。
tr接收到stdin后首先會把將結果按照某種標記符號進行換行。例如:
[root@xuexi tmp]# ls # 其中"one space.log"是帶有空格的文件名
a b c d logdir one one space.log shdir sh.txt space.log test vmware-root
將空格替換為制表符。因為tr一接收到數據就進行了排序換行,所以結果僅只替換了"one space.log"中的空格。
[root@xuexi tmp]# ls | tr " " "\t" # 結果是排序后換行的
a
b
c
d
logdir
one
one space.log
shdir
sh.txt
space.log
test
vmware-root
之所以說tr是映射而不是替換,是因為兩個結果集替換的時候符號位置是一一對應的。如果SET1比SET2短,則SET2多余的部分會被忽略,如果SET1比SET2長,POSIX認為這是不合理的,但也能執行,只不過結果有些意料之外,見下文。例如下面的例子,因為SET1中只有一個符號"\n",於是替換時SET2中的Y被忽略。
[root@xuexi tmp]# ls | tr "\n" "XY"
aXbXcXdXlogdirXoneXone space.logXshdirXsh.txtXspace.logXtestXvmware-rootX
這樣就可以實現簡單的加密和解密。
[root@xuexi tmp]# echo "12345" | tr "0-9" "9876543210" # 加密
87654
[root@xuexi tmp]# echo "87654" | tr "0-9" "9876543210" # 解密
12345
上面的過程是將管道左邊的12345對應到0-9的展開式0123456789,並將對應位映射到SET2的數字上。解密也是同理。
有一種ROT13加密算法,它的加密和解密使用一套字符。它的SET1的字母位和SET2的字母位完全反向成對。例如SET1指定符號是"axy",如果SET2想將其對應為"opq",則須將SET1擴展為"axyopq",SET2擴展為"opqaxy",最終是(a,x,y,o,p,q)和(o,p,q,a,x,y),這樣(a,o)和(o,a)就能成功配對。再將其擴展為A-Z和a-z,就是所謂的ROT13加密,甚至還可以將0-9也加上去和9-0對應。下面是SET1和SET2的對應式。
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
現在加密“I love you”
[root@xuexi tmp]# echo "I love you" | tr "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
V ybir lbh
將“V ybir lbh”解密。
[root@xuexi tmp]# echo "V ybir lbh" | tr "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
I love you
1.3 完全對應的替換
默認情況下,當指定的SET1比SET2字符長時,從最后一個對應的位置開始,SET1的剩余字符都和SET2的最后一個字符對應。假如SET1=[1234],SET2=[abc],則3對應c,4也對應c,此時如果tr的操作對象中出現3或者4都會被替換為c。
使用-t可以先截斷SET1比SET2中長的字符,例如上面截斷多余的4,SET1=[123]和SET2=[abc]就實現了完全對應。
[root@xuexi tmp]# cat x.txt
NO Name SubjectID Mark 備注
1 longshuai 001 56 不及格
2 gaoxiaofang 001 60 及格
3 zhangsan 001 50 不及格
4 lisi 001 80 及格
5 wangwu 001 90 及格
[root@xuexi tmp]# cat x.txt | tr "fang" "jin" # 結果中n和g都被替換為了n
NO Nime SubjectID Mirk 備注
1 lonnshuii 001 56 不及格
2 nioxiiojinn 001 60 及格
3 zhinnsin 001 50 不及格
4 lisi 001 80 及格
5 winnwu 001 90 及格
[root@xuexi tmp]# cat x.txt | tr -t "fang" "jin" # g被截斷,只對應替換fan為jin
NO Nime SubjectID Mirk 備注
1 longshuii 001 56 不及格
2 gioxiiojing 001 60 及格
3 zhingsin 001 50 不及格
4 lisi 001 80 及格
5 wingwu 001 90 及格
1.4 壓縮符號
這功能太爽了。
tr -s [SET1] [SET2]
如果不指定SET2,則僅只壓縮,不做替換。SET1可以指定多個字符,這樣會對每個字符都進行壓縮,例如tr -s "0a"
,即會壓縮連續的0,也會壓縮連續的a。如果指定了SET2,則壓縮后還一一對應地進行替換。
假如x.txt文件中的內容如下,空格有的地方多,有的地方少,也就是說這是一個沒有格式的文件。
[root@xuexi tmp]# cat x.txt
NO Name SubjectID Mark 備注
1 longshuai 001 56 不及格
2 gaoxiaofang 001 60 及格
3 zhangsan 001 50 不及格
4 lisi 001 80 及格
5 wangwu 001 90 及格
使用tr壓縮空格使其變的規則。
[root@xuexi tmp]# cat x.txt | tr -s " "
NO Name SubjectID Mark 備注
1 longshuai 001 56 不及格
2 gaoxiaofang 001 60 及格
3 zhangsan 001 50 不及格
4 lisi 001 80 及格
5 wangwu 001 90 及格
如果指定SET2,假如替換為"-"。
[root@xuexi tmp]# cat x.txt | tr -s " " "-"
NO-Name-SubjectID-Mark-備注
1-longshuai-001-56-不及格
2-gaoxiaofang-001-60-及格
3-zhangsan-001-50-不及格
4-lisi-001-80-及格
5-wangwu-001-90-及格
1.5 刪除符號和補集
tr -d
是刪除指定的符號,只能接一個SET1。
[root@xuexi tmp]# cat x.txt | tr -d " "
NONameSubjectIDMark備注
1longshuai00156不及格
2gaoxiaofang00160及格
3zhangsan00150不及格
4lisi00180及格
5wangwu00190及格
tr -c SET1 SET2
是將標准輸入按照SET1求補集,並將補集部分的字符全部替換為SET2,即將不在標准輸入中存在但SET1中不存在的字符替換為SET2的字符。但是SET2如果指定的字符大於1個,則只取最后一個字符作為替換字符。使用-c的時候應該把-c SET1作為一個整體,不要將其分開。
例如:
[root@xuexi tmp]# echo "abcdefo"| tr -c "ao" "y"
ayyyyyoy[root@xuexi tmp]#
標准輸入"abcdefo"按照SET1="ao"求得的補集為bcdef,將它們替換為y,結果即為ayyyyyo,但是結果的最后面多了一個y並且緊接着命令提示符。這是因為abcdefo尾部的\n也是ao的補集的一部分,並將其替換為y了。如果不想替換最后的\n,可以在SET1中指定\n。
[root@xuexi tmp]# echo "abcdefo"| tr -c "ao\n" "y"
ayyyyyo
如果SET2指定多個字符,將只取最后一個字符作為替換字符。
[root@xuexi tmp]# echo "abcdefo"| tr -c "ao\n" "ay"
ayyyyyo
[root@xuexi tmp]# echo "abcdefo"| tr -c "ao\n" "yb"
abbbbbo
"-c"常和"-d"一起使用,如tr -d -c SET1
。它先執行"-c SET1"求出SET1的補集,再對這個補集執行刪除。也就是說,最終的結果是完全匹配SET1中的字符。注意,"-d"一定是放在"-c"前面的,否則被解析為tr -c SET1 SET2
,執行的就不是刪除補集,而是替換補集為"-d"的最后一個字符d了。
[root@xuexi tmp]# echo "one 1 two 2 three 3"| tr -d -c "[0-9]\n" # 對數字和分行符求補集,並刪除這些補集符號
123
[root@xuexi tmp]# echo "one 1 two 2 three 3"| tr -d -c "[0-9] \n" # 再加一個空格求補集
1 2 3
[root@xuexi tmp]# echo "one 1 two 2 three 3"| tr -c "[0-9]\n" -d # -d選項放在-c選項的后面是替換行為
dddd1ddddd2ddddddd3
[root@xuexi tmp]# echo "one 1 two 2 three 3"| tr -d -c "[a-zA-z]\n" # 保留字母
onetwothree
[root@xuexi tmp]# echo "one 1 two 2 three 3"| tr -d -c "[a-zA-z] \n" # 保留字母的同時保留空格
one two three
從上面補集的實驗中可以看到,其實指定的[0-9]和[a-z]是一個字符類,最終的結果顯示的是這個類中的對象。
在tr中可以使用以下幾種字符類。這些類也可以用在其他某些命令中。
[:alnum:]
所有的數字和字母。[:alpha:]
所有的字母。[:blank:]
所有水平空白=空格+tab。[:cntrl:]
所有控制字符(非打印字符),在ascii表中的八進制0-37對應的字符和177的del。[:digit:]
所有數字。[:graph:]
所有打印字符,不包含空格=數字+字母+標點。[:lower:]
所有小寫字母。[:print:]
所有打印字符,包含空格=數字+字母+標點+空格。[:punct:]
所有標點符號。[:space:]
所有水平或垂直空白=空格+tab+分行符+垂直tab+分頁符+回車鍵。[:upper:]
所有大寫字母。[:xdigit:]
所有十六進制數字。
使用方法例如下面的。例如[:upper:]等價於[A-Z],[:digit:]等價於[0-9]。
[root@xuexi tmp]# echo "one ONE 1 two TWO 2 three THREE 3" | tr -d -c "[:upper:] \n"
ONE TWO THREE
[root@xuexi tmp]# echo "one ONE 1 two TWO 2 three THREE 3" | tr -d -c "[:alpha:] \n"
one ONE two TWO three THREE
[root@xuexi tmp]# echo "one ONE 1 two TWO 2 three THREE 3" | tr -d -c "[:digit:] \n"
1 2 3