Linux

Shell 腳本排序

  • November 23, 2018

我試圖對一個包含兩個單詞的條目進行排序,但我想將其排序為一個條目。

例如考慮這個小清單

peter barker painter
carl baker cook
joshua carpenter

這些都是名字和職業。現在說我想使用 sort 對這些條目進行排序。

問題是 sort 使用空格作為欄位,所以如果我 sort -k 1n 我將按名字排序

但我想按全名排序,然後也可以選擇按職業排序。如您所見,有些人沒有全名,約書亞只有他的名字和職業。所以對他來說,我只想按名字排序,但其他人的全名。

這可以實現嗎?

假設它只會失去姓氏(而不是名字)並且文件中的單詞不包含空格(這將使其非常困​​難),首先將數據轉換為製表符分隔的格式用空欄位替換缺少的姓氏:

$ awk -v OFS='\t' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file
peter   barker  painter
carl    baker   cook
joshua          carpenter

awk腳本將檢測包含兩個或三個欄位的行。它將簡單地將已經具有三個欄位的行重新格式化為三個製表符分隔的欄位,同時將最初僅包含兩個欄位的行的第二個欄位移動到第三個欄位。

然後使用製表符作為分隔符對數據進行排序:

$ awk -v OFS='\t' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t $'\t' -k1,2 -k3
carl    baker   cook
joshua          carpenter
peter   barker  painter

此處進行的排序是按全名(欄位一和二)然後按職業。假設您使用的 shellbash可以理解$'\t'為製表符。


除了製表符,您可以使用任何其他不干擾數據的字元(此處:):

$ awk -v OFS=':' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t ':' -k1,2 -k3
carl:baker:cook
joshua::carpenter
peter:barker:painter

然後通過傳遞結果來替換選擇的分隔符tr(這裡用製表符替換,因為它看起來不錯):

$ awk -v OFS=':' 'NF == 3 { $1 = $1 } NF == 2 { $3 = $2; $2 = "" } { print }' <file | sort -t ':' -k1,2 -k3 | tr ':' '\t'
carl    baker   cook
joshua          carpenter
peter   barker  painter

引用自:https://unix.stackexchange.com/questions/483710