最近,我不得不根據記錄的ID對幾個檔案進行排序;問題是可以有幾種型別的記錄,在每種型別中,我必須用于排序的欄位位于不同的位置。然而,由于key=value結構,這些欄位很容易識別。顯示一般結構的簡單示例:
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3
我想出了一個如下管道,它完成了這項作業:
awk -F'[|=]' '{for(i=1; i<=NF; i ) {if($i ~ "id") {i ; print $i"?"$0} }}' tester.txt | sort -n | awk -F'?' '{print $2}'
換句話說,演算法如下:
- 通過欄位和鍵值分隔符(
|和=)拆分記錄 - 遍歷元素并搜索
id鍵 - 列印下一個元素(
id鍵的值)、分隔符和整行 - 按數字排序
- 洗掉前置識別符號以保留記錄的結構
處理樣本給出輸出:
fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3
但是,有沒有辦法使用單個awk命令來完成這項任務?
uj5u.com熱心網友回復:
gnu-awk您可以在單個命令中嘗試此代碼:
awk -F'|' '{
for(i=1; i<=NF; i)
if ($i ~ /^id=/) {
a[gensub(/^id=/, "", 1, $i)] = $0
break
}
}
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
for (i in a)
print a[i]
}' file
fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3
我們使用|作為欄位分隔符,當有一個以開頭的列名時,id=我們將其存盤在陣列a中,索引作為文本之后=,值作為完整記錄。
使用我們使用索引的數值PROCINFO["sorted_in"] = "@ind_num_asc"對陣列進行排序,然后在 for 回圈中我們列印值部分以獲取排序后的輸出。a
uj5u.com熱心網友回復:
使用 GNU awk 作為第三個引數match()和sorted_in:
$ cat tst.awk
match($0,/(^|\|)id=([0-9] )/,a) {
ids2vals[a[2]] = $0
}
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
for ( id in ids2vals ) {
print ids2vals[id]
}
}
$ awk -f tst.awk file
fieldD=valueD|recordType=B|id=1|fieldE=valueE
fieldA=valueA|fieldB=valueB|recordType=A|id=2|fieldC=valueC
fieldF=valueF|fieldG=valueG|fieldH=valueH|recordType=C|id=3
uj5u.com熱心網友回復:
試試 Perl:perl -e 'print map { s/^.*? //; $_ } sort { $a <=> $b } map { ($id) = /id=(\d )/; "$id $_" } <>' file
我使用的代碼的一些解釋:
print #print the resulting list of lines
map {
s/^.*? //;
$_
} #remove numeric id from start of line
sort { $a <=> $b } #sort numerically
map {
($id) = /id=(\d )/;
"$id $_"
} # capture id and place it in start of line
<> # read all lines from file
sed或嘗試sort:sed 's/^\(.*id=\([0-9][0-9]*\).*\)$/\2 \1/' file | sort -n | sed 's/^[^ ][^ ]* //'
uj5u.com熱心網友回復:
僅使用您顯示的示例,請嘗試以下(awk sort)cut解決方案,在 GNU 中撰寫和測驗awk,應該適用于任何awk.
awk '
match($0,/id=[0-9] /){
print substr($0,RSTART,RLENGTH)";"$0
}
' Input_file | sort -t'=' -k2n | cut -d';' -f2-
說明:為上述代碼添加詳細說明。
awk ' ##Starting awk program from here.
match($0,/id=[0-9] /){ ##Using awk match function to match id= followed by digits.
print substr($0,RSTART,RLENGTH)";"$0 ##printing sub string of matched value followed by current line along with semi-colon in it.
}
' Input_file | ##Mentioning Input_file here and passing awk output as a standard input to next command.
sort -t'=' -k2n | ##Sorting output with delimiter of = and by 2nd field then passing output to next command as an input.
cut -d';' -f2- ##Using cut command making delimiter as ; and printing everything from 2nd field onwards.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/478109.html
下一篇:在檔案夾串列中查找檔案夾位置編號
