首頁 > 軟體

Linux sort命令中文手冊(info sort翻譯)

2020-06-16 17:09:07

說明:

(1).本手冊只挑選了有用的資訊進行翻譯,如要檢視完完整整的內容,請自行info sort。

(2).譯文中,在括號中使用了"註"的,為本人所加,非原文內容,助於理解和說明。

(3).本文的sort命令為CentOS 7.2上的,版本為sort (GNU coreutils) 8.22,有些選項在CentOS 6上可能不支援,如"--debug"。

(4).在沒搞懂sort處理欄位和排序機制時,強烈建議不要看man sort。

7.1 'sort': Sort text files

===========================

sort命令用於排序、合併或比較給定檔案(可給定多個)的所有行,如果沒有給定輸入檔案或輸入檔案為"-",則讀取標准輸入。預設情況下,sort將操作結果列印在標準輸出中。

語法:

sort [OPTION]... [FILE]...

sort有3種操作模式:排序(預設)、合併以及檢查是否已經排過序。使用以下3個選項改變操作模式:

'-c'
'--check'
'--check=diagnose-first'
檢查給定檔案是否已經排序過:如果檢測出未排序,將輸出診斷資訊並以狀態碼1退出,該診斷資訊中包含第一個亂序的行。否則以成功狀態退出。最多只能給定一個檢測檔案。

 

'-C'
'--check=quiet'
'--check=silent'
它類似於"-c",但不會輸出診斷資訊。如果檔案已排序,則以成功狀態退出,否則以狀態碼1退出。最多只能給定一個檔案。

 

'-m'

'--merge'
合併多個檔案,每個輸入檔案必須已經排序。合併時將根據已排序的結果合併為各個組。sort一般都用來排序,但仍然提供合併功能,因為它的合併速度很快。

 

sort排序規則為:按照命令列中給定的欄位順序對給定的欄位進行排序,排序時根據為每個欄位分配的排序選項進行排序,直到發現不同的排序選項或者排序列結束。如果沒有給定排序key(註:key即為-k指定的值),則對整行進行排序。最後,如果所有給定的key的比較結果都相等時,將對整行進行完全預設的排序(註:即以字母升序排序),但"-r"可以改變這次的升、降序結果。這次排序稱為"最後的排序"。使用"-s"選項可以禁止"最後的排序",使得那些排序結果相同的行保留最初的相對順序。"-u"選項同樣也會禁止"最後的排序"。

除非明確指定,否則所有的比較都按照"LC_COLLATE"指定的字元集的排序規則進行排序。

 

退出狀態碼:

0 沒有任何錯誤發生時
1 如果"-c"或"-C"檢測發現輸入資料未排序時
2 發生了錯誤時

如果設定了環境變數"TMPDIR",sort將使用它作為臨時目錄而不是預設的"/tmp"。"-T"選項將覆蓋該環境變數設定的值。

以下選項影響排序的輸出結果。它們既可以指定為全域性選項,也可以作為key的一部分。如果未指定任何key,則全域性選項將作用於整行,否則指定的key將繼承全域性選項,除非key自身也指定了選項(注:自身指定了選項的key將覆蓋全域性選項)。

為了考慮可移植性,建議將全域性選項指定在"-k"(或"--key")的前面。


'-b'
'--ignore-leading-blanks'
忽略key的前導空白符號(包括空格、製表符)。不給定該選項時,空白符號對"-k"選項指定字元位置有影響(註:例如"-k 2.2"指定的第2個字元可能是空白)。

 

'-f'
'--ignore-case'
將小寫字元當作大寫字元。例如,"b"和"B"是相等的。當和"-u"選項一起使用時(注:重複的行只能輸出一次),那些小寫字元的等價行會被丟棄(註:也就是說,輸出的是大寫字元行)。(目前沒有任何方法可以拋棄大寫字元的等價行,即使使用"-r"也不行,因為在任何時,"-r"選項都只是反轉最終的排序結果,不會影響排序過程)。

 

'-h'
'--human-numeric-sort'
'--sort=human-numeric'
對檔案大小格式進行排序。首先對正負性排序(正數>0>負數),再對大小字尾排序(0<k=K<M<G<T...),最後對數值排序。它不在乎轉換精度是1000還是1024,因為它總會自動不斷擴大到最接近的字尾(注:例如999M和1G比較時將以1000作為轉換單位,1023M和1G比較時將以1024作為轉換單位)。

 

'-M'
'--month-sort'
'--sort=month'
按字元格式的月份進行排序。
An initial string, consisting of any amount of blanks, followed by a month name abbreviation, is folded to UPPER case and compared in the order 'JAN' < 'FEB' < ... < 'DEC'. Invalid names compare low to valid names.

 

'-n'
'--numeric-sort'
'--sort=numeric'
按數值排序。空字串""或""被當作無。數值排序是精確排序,不會四捨五入後排序。

(註:數值排序和預設的排序規則所不同的是,當key中遇到非數學字元時,如空白、字母、特殊字元等,將直接結束排序(在sort內部認為找不到匹配值)。也就是說,"-k 2"和"-k 2n"不同,雖然這兩個key都會擴充套件到行尾,前者會從第二個欄位一直按字元集順序比較到行尾,而後者可能只對第2欄位匹配,因為第二欄位和第三欄位中間可能有特殊符號,導致數值排序直接結束。

因此,對於"abc 100 200"這樣的輸入,假設欄位分隔符為空格,當指定"-k 2n"時,該key為"100 200",但由於中間包含了空白,使得該key的排序在第二欄位就結束。如果是"abc 100200 200","-k 2n"在排序時,雖然看上去是100200,但卻只對100進行排序,也就是說,如果此時另有一行第2欄位值為110,看上去很大的100200將小於110。測試語句:

echo -e "b 100:200 200na 110 300" | tr ':' ''|sort -t ' ' -k2n -k1

因此,對於"-n"來說,它絕對不可能跨越key的邊界。但預設的排序規則會跨越key起作用。)

 

'-r'
'--reverse'
反轉比較的結果,使得結果中更大的key更早出現。(註:"-r"不會改變排序行為,而是將排序結束後的輸出結果進行反轉處理,因此只影響排序結束後的輸出結果)

 

'-k POS1[,POS2]'
'--key=POS1[,POS2]'
指定排序的key,即每行排序的起始和終止欄位(若省略POS2,則終止位置為行尾)。

POS的格式為"F[.C][OPTS]",其中F表示欄位的序號,C表示該欄位中字元的序號。欄位和字元的位置都從1開始計算。如果POS2的字元位置指定為0,則表示POS2欄位中的最後一個字元。如果POS1中省略".C",則預設值為1(欄位的起始字元),如果POS2中省略".C",預設值為0(欄位的終止字元)。OPTS為排序選項,這些選項將覆蓋全域性選項,使得該key可以按照獨立的排序選項進行排序。keys可以跨多個欄位。
(註:OPTS指定在POS1和POS2的作用是一樣的,因為一個"-k"指定一個key,無論是POS1還是POS2中的OPTS都是對這個key有效,但"b"選項除外,見下文)

範例:為了排序第二個欄位,使用"--key=2,2"(-k 2,2)。可使用"--debug"選項幫助檢視、分析和決定每行中被用於排序的欄位。

 

'--debug'
顯示每行中用於排序的部分。還會給出額外的資訊。

 

'-o OUTPUT-FILE'
'--output=OUTPUT-FILE'
將排序的輸出結果寫入到OUTPUT-FILE中。一般來說,sort在開啟OUTPUT-FILE前讀取完所有輸入,因此可以安全地將排序結果儲存到輸入檔案中,就像"sort -o file1 file1"和"cat file1 | sort -o file1"一樣。但是,"-m"選項會在讀取輸入前先開啟輸出檔案,因此下面的語句是不安全的語句:

"cat file1 | sort -m -o file1 -"

 

'-s'
'--stable'
禁止sort執行"最後的排序"。在沒有指定欄位選項或全域性選項時,該選項將不起作用,除非指定的是"-r"選項。
(註:最後的排序:在key的比較結果相同時,sort的最後手段是對整行再進行一次完全預設的排序,即按照字母、升序對整行做最後排序。這稱為"最後的排序"。如果未指定任何選項,其本身就是完全預設的,因此沒必要再做最後的排序。如果指定的是"-r"選項,由於"-r"是對最終結果進行反轉排序,因此會影響這次的"最後的排序"的結果)

 

'-t SEPARATOR'
'--field-separator=SEPARATOR'
當在每行中搜尋key的時候,使用SEPARATOR字元作為欄位的分隔符。預設情況下,欄位是由空白字元和非空白字元之間的空字串分割而來的。

因此,如果輸入行為" foo bar",預設將切分為兩個欄位" foo"和" bar",(註:空白和非空白字元之間的空字元為行開頭和"oo"後的位置)。欄位分隔符不是分隔後欄位中的內容,因此"sort -t ' '"對" foo bar"分隔時,將分割為3個欄位:空欄位、"foo"和"bar"。但是,每個單獨的欄位都是擴充套件到行結尾的,就像"-k 2",或像"-k 2,3"包含了範圍的欄位,它們都在擴充套件的時候保留欄位分隔符。
(註:以sort -t ' '為例,"-k 2"實際上表示的是"foo bar",它擴充套件到行尾,且中間的欄位分隔符被保留。而"-k 1,2"實際上表示的是" foo",因為明確指定了這個key到第二個欄位結束,但中間的欄位分隔符仍保留)
如果要指定欄位分隔符為空,則使用"",例如"sort -t ''"。

 

'--parallel=N'
設定sort執行的並行執行緒數為N。預設N設定為可獲得的cpu個數,但最大限制為8,因為超過8之後帶來的效能收益遞減。

 

'-u'
'--unique'
一般情況下,"-u"將僅輸出排序後重複行的第一行。該選項會禁止"最後的排序"(註:見前文譯文)。

 

"sort -u"和"sort | uniq"是等價的,但擴充套件了更多選項後將可能不???價,例如,"sort -n -u"只會檢查數值部分的唯一性,但"sort -n | uniq"在sort對行的數值排序後,uniq將檢查整個行的唯一性。

 

'-z'
'--zero-terminated'
使用""分割每行而不是使用換行符。

 

"-k"指定的key後面可以指定"bfhgnr"等選項,這種情況下,該key將不會繼承全域性選項。除了"b"選項,所有的選項都作用於整個key,無論該選項是寫在POS1還是POS2上。如果指定了"b"選項,它僅獨立作用於POS1或POS2上,但如果繼承了全域性的"-b",則會作用於整個key上。如果輸入行中包含了前導空白字元,且沒有使用"-t"選項,"-k"通常會結合"-b"或某些隱含了忽略前導空白字元的選項(ghn)一起使用,否則前導空白字元可能會導致劃分的欄位非常混亂。

如果POS中指定的欄位或字元位置超出了行尾或欄位,則該key為空。如果指定了"-b"選項,".C"部分將從欄位的第一個非空白字元開始計算。

以下是一些範例,用於說明不同選項的結合使用:

  •  按數值排序,並降序(reverse)
sort -n -r
  •  按字母排序,忽略第一和第二欄位,且忽略第三欄位的前導空白。此處使用了單個key,該key從第三欄位非空白字元開始,一直擴充套件到行的結尾。這一整個key都採用字母排序。
sort -k 3b
  • 對第二欄位按數值排序,並通過指定第五欄位的第3、4字元間按字母排序來解除按數值排序的規則。使用":"作為欄位分隔符。
sort -t : -k 2,2n -k 5.3,5.4

(註:任何時候,只想對某欄位進行排序時,都建議明確指定其起始和結束位置)

注意,如果寫的是"-k 2n"而不是"-k 2,2n",該key將從第二欄位一直擴充套件到行尾,這是主排序key,而副排序key"-k 5.3,5.4"在主排序key的排序基礎上再按照字母排序。絕大多數情況下,讓key向後擴充套件一般不是所期望的行為。

還需注意,"n"選項作用範圍為第一個key。這等價於"-k 2n,2"或"-k 2n,2n"。所有的修飾符,除了"-b",無論寫在pos1還是pos2,都會作用於整個key。

(註:由於n選項無法跨越key,因此上面即使寫成了"-k 2n"也是等價的,但下面兩個命令則不一樣:

sort -t : -k 2 -k 5.3,5.4n
sort -t : -k 2,2 -k 5.3,5.4n

由於預設的字元集排序規則會跨越key,第一條命令中主key從第2欄位開始,直到行尾結束,於是會先對整個key按字元排序,然後在此基礎上再對副key按數值排序。
再如下面的例子:即使主key的欄位在副key的欄位後面,副key由於是做字元集排序,所以仍會跨越主key。)

sort -t : -k 5n -k 2
  • 對/etc/passwd檔案的第5欄位排序,並忽略前導空白。如果第5欄位排序結果相等,則進一步按數值對第3欄位的uid進行排序。欄位分隔符為":"。
sort -t : -k 5b,5 -k 3,3n /etc/passwd
sort -t : -n -k 5b,5 -k 3,3 /etc/passwd
sort -t : -b -k 5,5 -k 3,3n /etc/passwd

以上三個命令是等價的。第一個命令指定了第一個key的POS1要忽略前導空白,且第二個key要按照數值排序。另外兩個命令中,缺少選項的key將繼承全域性選項。此處繼承之所以能正確工作,是因為"-k 5b,5b"和"-k 5b,5"是等價的。

  • 對一系列紀錄檔檔案進行排序,主排序key為IPv4,副排序key為時間戳。如果兩行的主、副key都完全一致,則按照檔案被讀取時的相對順序輸出。紀錄檔檔案包含的行格式大致如下:

4.150.156.3 - - [01/Apr/2004:06:31:51 +0000] message 1
211.24.3.231 - - [24/Apr/2004:20:17:39 +0000] message 2

使用單個空格可以精確分割這些欄位。IPV4地址列按照字典順序排序,例如212.61.52.2小於212.129.233.201,因為61小於129。

sort -s -t ' ' -k 4.9n -k 4.5M -k 4.2n -k 4.14,4.21 file*.log |
sort -s -t '.' -k 1,1n -k 2,2n -k 3,3n -k 4,4n

該範例無法僅使用一個sort語句實現,因為IPV4地址需要使用"."分隔,而時間戳需要使用空格分隔。因此,使用兩個sort語句:第一個sort語句按照時間戳排序,第二個語句按照IPV4排序。第一個sort命令中使用"-k"將每個欄位進行隔離,先按照年排序,再按照月份排序,接著是日,最後對"時:分:秒"排序。除了"時:分:秒"這個key,其餘的key都沒必要指定key的結束位置,因為"n"和"M"選項作用範圍不能跨域每個key的左邊界。第二個sort命令是對ipv4地址按照字典順序排序的。第二個sort語句中使用了"-s"選項,以防止主排序key的關係被副排序key破壞,第一個sort語句中使用"-s"選項是為了保證兩個sort語句在"-s"屬性上的一致性。

(註:由於n選項無法跨越key邊界和非數學字元,因此上面第二個sort命令和下面的命令是等價的:)

sort -s -t '.' -n -k1 -k2 -k3 -k4

本文永久更新連結地址http://www.linuxidc.com/Linux/2017-08/146533.htm


IT145.com E-mail:sddin#qq.com