SHELL腳本--tr命令用法和特性全解


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM