【轉】linux中的cut/tr/join/split/xargs命令

myLittleGarden發表於2013-11-07

1. cut命令

cut命令用於從檔案或者標準輸入中讀取內容並擷取每一行的特定部分並送到標準輸出。

擷取的方式有三種:
一是按照字元位置,二是按照位元組位置,
三是使用一個分隔符將一行分割成多個field,並提取指定的fields。

cut命令有5個引數,其中-c,-b,-f分別表示"character", "byte"以及"field"擷取方式。
當採用field模式擷取時,需要用"-d"引數指定一個分隔符,分割符只能為單個字元。另外還有一個"-s",suppress,表示如果行中沒有給出的分割符則不輸出該行(預設為如果沒有分隔符則將該行原封不動輸出)

以下為幾個例子:

按字元擷取:echo hello, world | cut -c 8-12 則輸出"world"(擷取字串中從第8到第12個共12個字元)
按分隔符擷取:echo hello, world | cut -f 2 -d " "則輸出"world"(擷取以空格分割的第二部分)
echo Long, long ago | cut -f 2,3 -d " "則輸出" long ago"(擷取以空格分割的第2、3部分,注意輸出的結果也以-d指定的分隔符分割)
使用"-s"安靜地忽略沒有給出地分隔符地行:echo hello |cut -d "!" -f 1 -s則什麼也不輸出(因為行中沒有"!"字元)
如果命令執行成功則返回0,遇到錯誤則返回一個大於0的數字。

其中-c,-b,好理解,下面我自己理解的-f引數,自己多試驗幾次,多輸出幾次,就明白了。

    # echo Long,long ago,ddddddd | cut -f 2 -d ,
    long ago

    # echo Long,long ago,ddddddd | cut -f 2- -d ,
    long ago,ddddddd

    # echo Long,long ago,ddddddd,hhhhhhhhhhh | cut -f 2- -d ,
    long ago,ddddddd,hhhhhhhhhhh

 上面三個對比一下就會很清楚。

# echo Long,long ago,ddddddd | cut -f 2,3 -d ,
long ago,ddddddd
# echo Long,long ago,ddddddd | cut -f 1,3 -d ,
Long,ddddddd
# echo Long,long ago,ddddddd | cut -f 1,2 -d ,
Long,long ago
# echo Long,long ago ddddddd | cut -f 2 -d ,
long ago ddddddd

# echo Long,long ago ddddddd | cut -f 2,3 -d ,
long ago ddddddd

2. tr命令

     通過使用 tr,您可以非常容易地實現 sed 的許多最基本功能。您可以將 tr 看作為 sed 的(極其)簡化的變體:它可以用一個字元來替換另一個字元,或者可以完全除去一些字元。您也可以用它來除去重複字元。這就是所有 tr 所能夠做的。     
     tr用來從標準輸入中通過替換或刪除操作進行字元轉換。tr主要用於刪除檔案中控制字元或進行字元轉換。使用tr時要轉換兩個字串:字串1用於查 詢,字串2用於處理各種轉換。tr剛執行時,字串1中的字元被對映到字串2中的字元,然後轉換操作開始。
   帶有最常用選項的tr命令格式為:

tr -c -d -s ["string1_to_translate_from"] ["string2_to_translate_to"] < input-file

 這裡:
-c 用字串1中字符集的補集替換此字符集,要求字符集為ASCII。
-d 刪除字串1中所有輸入字元。
-s 刪除所有重複出現字元序列,只保留第一個;即將重複出現字串壓縮為一個字串。
input-file是轉換檔名。雖然可以使用其他格式輸入,但這種格式最常用。

指定字串1或字串2的內容時,只能使用單字元或字串範圍或列表。
[a-z] a-z內的字元組成的字串。
[A-Z] A-Z內的字元組成的字串。
[0-9] 數字串。
\octal 一個三位的八進位制數,對應有效的ASCII字元。
[O*n] 表示字元O重複出現指定次數n。因此[O*2]匹配OO的字串。
tr中特定控制字元的不同表達方式
速記符含義八進位制方式
\a Ctrl-G  鈴聲\007
\b Ctrl-H  退格符\010
\f Ctrl-L  走行換頁\014
\n Ctrl-J  新行\012
\r Ctrl-M  回車\015
\t Ctrl-I  tab鍵\011
\v Ctrl-X  \030

例項:

 將檔案file中出現的"abc"替換為"xyz"
 # cat file | tr "abc" "xyz" > new_file
 【注意】這裡,凡是在file中出現的"a"字母,都替換成"x"字母,"b"字母替換為"y"字母,"c"字母替換為"z"字母。而不是將字串"abc"替換為字串"xyz"。

使用tr命令“統一”字母大小寫
(小寫 --> 大寫)
# cat file | tr [a-z] [A-Z] > new_file
(大寫 --> 小寫)
# cat file | tr [A-Z] [a-z] > new_file

把檔案中的數字0-9替換為a-j
 # cat file | tr [0-9] [a-j] > new_file

刪除檔案file中出現的"Snail"字元
 # cat file | tr -d "Snail" > new_file
 【注意】這裡,凡是在file檔案中出現的'S','n','a','i','l'字元都會被刪除!而不是緊緊刪除出現的"Snail”字串。

刪除檔案file中出現的換行'\n'、製表'\t'字元
 # cat file | tr -d "\n\t" > new_file
 不可見字元都得用轉義字元來表示的,這個都是統一的。

刪除“連續著的”重複字母,只保留第一個
 # cat file | tr -s [a-zA-Z] > new_file

刪除空行
 # cat file | tr -s "\n" > new_file

刪除Windows檔案“造成”的'^M'字元
 # cat file | tr -d "\r" > new_file
 【注意】這裡-s後面是兩個引數"\r"和"\n",用後者替換前者

用空格符\040替換製表符\011
 # cat file | tr -s "\011" "\040" > new_file

把路徑變數中的冒號":",替換成換行符"\n"
 # echo $PATH | tr -s ":" "\n"

3. join命令

join命令
   功能:“將兩個檔案中指定欄位相同的行連線起來”,即按照兩個檔案中共同擁有的某一列,將對應的行拼接成一行。
 join [options] file1 file2
     注:這兩個檔案必須在已經在此列上是按照相同的規則進行了排序。
join選項
   -a FILENUM:除了顯示匹配好的行另外將指定序號(1或2)檔案中部匹配的行顯示出來
   -e EMPTY:將需要顯示但是檔案中不存在的域用此選項指定的字元代替
   -i :忽略大小寫
   -j FIELD :等同於 -1 FIELD -2 FIELD,-j指定一個域作為匹配欄位
   -o FORMAT:以指定格式輸出
   -t CHAR :以指定字元作為輸入輸出的分隔符
          join 預設以空白字元做分隔符(空格和\t),可以使用 join -t $'\t'來指定使用tab做分隔符
   -v FILENUM:與-a相似 但值顯示檔案中沒匹配上的行
   -1 FIELD:以file1中FIELD欄位進行匹配
   -2 FIELD:以file2中FIELD欄位進行匹配
   --help :列印命令幫助檔案
例子:
檔案 file1.txt
    aa 1 2
    bb 2 3
    cc 4 6
    dd 3 3
檔案file2.txt

    aa 2 1
    bb 8 2
    ff 2 4
    cc 4 4
    dd 5 5

1.join file1.txt file2.txt
 輸出:aa 1 2 2 1
       bb 2 3 8 2
  預設已兩個檔案的第一行做匹配欄位,預設以空格(不限個數)做分隔符。
2.join -j 1 file1.txt file2.txt
輸出:aa 1 2 2 1
      bb 2 3 8 9
 -j選項 指定了以兩個檔案中第一列做匹配欄位 等同於join file1.txt file2.txt
3. join -1 2 -2 3 file1.txt file2.txt
輸出: 1 aa 2 aa 2
     2 bb 3 bb 8
     4 cc 6 ff 2
     4 cc 6 cc 4
 以第一個檔案的第二列和第二個檔案的第三列做匹配欄位。由於第二個檔案中第三列的兩個3 都與第一個檔案中第三行因此輸出
    4 cc 6 ff 2
    4 cc 6 cc 4
4 join -o 1.1 -o 1.2  -o 1.3 -o 2.1 -o 2.2 -o 2.3   -e 'empty' -a 1  file1.txt file2.txt 
輸出: aa 1 2 aa 2 1
       bb 2 3 bb 8 2
    cc 4 6 empty empty empty
    dd 3 3 empty empty empty
 -o 指定 將file1的1,2,3列,file2的1,2,3 列都輸出。-a指定將file1中不匹配的行也輸出,但是file2中沒有與file1後兩行對應的欄位,因此使用empty補齊。

5.join  -v 1  file1.txt file2.txt 
  輸出: cc 4 6
         dd 3 3
 -v 1 將file1中不匹配的行輸出
PS:join命令和資料庫中的join命令很類似。
    雖然file1和file2都已經排序,但是由於在第三行時開始不匹配因此只匹配上了前兩行,後面的行雖然欄位也可以對應但是以不能匹配。join命令,對檔案格式的要求非常強,如果想要更靈活的使用,可用AWK命令,參加AWK例項

6. join 標準輸入
  有時我們需要將多個格式相同的檔案join到一起,而join接受的是兩個檔案的指令,此時我們可以使用管道和字元“-"來實現
    join file1 file2 | join - file3 | join - file4 
  這樣就可以將四個檔案 連線到 一起了。 

4. split命令

否想要把一個大檔案分割成多個小檔案?比如一個5gb日誌檔案,我們需要把它分成多個小檔案,這樣我們才有可能使用普通的文字編輯器讀取 它。有時我們需要傳輸20gb的大檔案到另一臺伺服器,這就需要我們把它分割成多個檔案,這樣便於傳輸資料。下面我們來通過五個例項來講解它。
 
例項1、以每個檔案1000行分割
split命令分割檔案成每個檔案1000行,並且檔名依次為 [字首]aa, [字首]ab, [字首]ac等,預設的字首是X,每個檔案的行數為1000行,命令如下:
$ split mylog
$ wc -l *
4450 mylog
1000 xaa
1000 xab
1000 xac
1000 xad
450 xae

 

例項2、以每個檔案20MB分割

分割檔案為多個20MB的檔案,附帶-b選項命令如下:

    $ split -b 20M logdata
    $ ls -lh | tail -n +2
    -rw------- 1 sathiya sathiya 102M Jul 25 18:47 logdata
    -rw------- 1 sathiya sathiya  20M Jul 25 19:20 xaa
    -rw------- 1 sathiya sathiya  20M Jul 25 19:20 xab
    -rw------- 1 sathiya sathiya  20M Jul 25 19:20 xac
    -rw------- 1 sathiya sathiya  20M Jul 25 19:20 xad

 

例項3、以每個檔案50MB指定字首分割

使用–bytes選項把檔案分割成多個50MB的檔案,–bytes類似-b選項,在第二個引數指定字首。

    $ split --bytes=50M logdata mydatafile
    $ ls -lh
    total 204M
    -rw------- 1 sathiya sathiya 102M Jul 25 18:47 logdata
    -rw------- 1 sathiya sathiya  50M Jul 25 19:23 mydatafileaa

 

例項4、基於行數分割檔案

使用-l選項指定行數來把檔案分割成多個行數相同的檔案。

    $ wc -l testfile
    2591 testfile
    $ split -l 1500 testfile importantlog
    $ wc -l *
    1500 importantlogaa
    1091 importantlogab
    2591 testfile

 

例項5、以數字字尾命名分割檔案

使用-d選項可以指定字尾為數字,如00,01,02..,而不是aa,ab,ac。

    $ split -d testfile
    $ ls
    testfile  x00  x01  x02
可用選項

短 選項長選項選項描述-b–bytes=SIZESIZE 值為每一輸出檔案的大小,單位為 byte。-C–line-bytes=SIZE每一輸出檔中,單行的最大 byte 數。-d–numeric-suffixes使用數字作為字尾。-l–lines=NUMBERNUMBER 值為每一輸出檔的列數大小。

測試的時候發現-b 選項老提示出錯,沒查什麼原因,改成--bytes=20000000 了

另外可以複合使用這些選項   比如

split -d --bytes=20000000 testfile aaa_

這樣出來的檔案是

aaa_00,aaa_01,…… aaa_...


5. xargs命令

xargs是給命令傳遞引數的一個過濾器,也是組合多個命令的一個工具。它把一個資料流分割為一些足夠小的塊,以方便過濾器和命令進行處理。通常情況下,xargs從管道或者stdin中讀取資料,但是它也能夠從檔案的輸出中讀取資料。xargs的預設命令是echo,這意味著通過管道傳遞給xargs的輸入將會包含換行和空白,不過通過xargs的處理,換行和空白將被空格取代。

xargs 是一個強有力的命令,它能夠捕獲一個命令的輸出,然後傳遞給另外一個命令,下面是一些如何有效使用xargs 的實用例子。

1. 當你嘗試用rm 刪除太多的檔案,你可能得到一個錯誤資訊:/bin/rm Argument list too long. 用xargs 去避免這個問題
find ~ -name ‘*.log’ -print0 | xargs -0 rm -f
 

2. 獲得/etc/ 下所有*.conf 結尾的檔案列表,有幾種不同的方法能得到相同的結果,下面的例子僅僅是示範怎麼實用xargs ,在這個例子中實用 xargs將find 命令的輸出傳遞給ls -l
# find /etc -name "*.conf" | xargs ls –l

3. 假如你有一個檔案包含了很多你希望下載的URL, 你能夠使用xargs 下載所有連結
# cat url-list.txt | xargs wget –c
 
4. 查詢所有的jpg 檔案,並且壓縮它
# find / -name *.jpg -type f -print | xargs tar -cvzf images.tar.gz

5. 拷貝所有的圖片檔案到一個外部的硬碟驅動 
# ls *.jpg | xargs -n1 -i cp {} /external-hard-drive/directory

 

相關文章