[英]Error in sorting based on a specific column in bash
注意:假設輸入文件的列由空格而不是制表符分隔,否則 dan 的注釋 - sort -nt $'\t' -k3,3
- 就足夠了
sort
允許我們指定字段終止符以及要排序的字段(以及可選的字段子字符串)。
如果我們將字段分隔符設置為換行符 ( \n
),則整行將變為單個字段。
從這里我們可以指定字段 #1 的子字符串作為排序依據; -k1.x,1.y
表示按字段 #1 從位置x
到位置y
排序(字段/行的第一個字符的位置為1
)。
樣本輸入:
$ cat animals.txt
1 2 3 4 5 6
123456789012345678901234567890123456789012345678901234567890
alpaca Intermediate Perl 2012 Schwatz, Randal
donkey Cisco IOS in a Nutshell 2005 Boney, James
horse Linux in a Nutshell 2009 Siever, Ellen
在哪里:
year
部分從位置36
到39
將所有這些都放入一個sort
調用中:
# sort numerically by year (ascending)
$ sort -t$'\n' -k1.36,1.39 -n animals.txt
donkey Cisco IOS in a Nutshell 2005 Boney, James
horse Linux in a Nutshell 2009 Siever, Ellen
alpaca Intermediate Perl 2012 Schwatz, Randal
# sort numerically by year (descending)
$ sort -t$'\n' -k1.36,1.39 -rn animals.txt
alpaca Intermediate Perl 2012 Schwatz, Randal
horse Linux in a Nutshell 2009 Siever, Ellen
donkey Cisco IOS in a Nutshell 2005 Boney, James
注意:假設所有行的year
都在同一位置(即文件的內容按照固定寬度方案進行格式化)
顯然這種方法需要我們提前知道year
子串的位置; 有幾種方法可以確定這個位置......一個想法,假設year
列總是第一次出現 4 位子字符串......使用bash
正則表達式匹配和BASH_REMATCH[]
數組來確定排列到 4 位數的year
,例如:
$ regex="^([^0-9]*)([0-9]{4}).*"
$ [[ $(head -1 animals.txt) =~ $regex ]] && typeset -p BASH_REMATCH
declare -ar BASH_REMATCH=([0]="alpaca Intermediate Perl 2012 Schwatz, Randal" [1]="alpaca Intermediate Perl " [2]="2012")
從這里我們看到BASH_REMATCH[1]
包含該行的內容,直到year
( 2012
用於alpaca
行); 現在我們獲取BASH_REMATCH[1]
的長度並添加 +1/+3 以獲得我們的x
和y
值:
$ (( x = ${#BASH_REMATCH[1]} + 1 ))
$ (( y = x + 3 ))
$ typeset -p x y
declare -- x="36"
declare -- y="39"
將這些變量插入到我們之前的sort
調用中:
# sort numerically by year (ascending)
$ sort -t$'\n' -k1.${x},1.${y} -n animals.txt
donkey Cisco IOS in a Nutshell 2005 Boney, James
horse Linux in a Nutshell 2009 Siever, Ellen
alpaca Intermediate Perl 2012 Schwatz, Randal
# sort numerically by year (descending)
$ sort -t$'\n' -k1.${x},1.${y} -rn animals.txt
alpaca Intermediate Perl 2012 Schwatz, Randal
horse Linux in a Nutshell 2009 Siever, Ellen
donkey Cisco IOS in a Nutshell 2005 Boney, James
注意:在多行具有相同日期的情況下,OP 沒有定義二級排序要求,但擴展這個答案以包括二級(和三級?)排序要求應該不會太難
嘗試添加逗號之類的分隔符,因為從那里您將能夠使用帶有-t
參數的sort
命令並指定給定的字段分隔符。
要查找並用分隔符替換字符,我會使用cat animals.txt | sed {insert the pattern}
cat animals.txt | sed {insert the pattern}
。
根據您共享的文件,您可以嘗試在第一個單詞之后以及數值之前和之后添加分隔符。
注意:假設輸入文件的列由空格而不是制表符分隔,否則 dan 的注釋 - sort -nt $'\t' -k3,3
- 就足夠了
如果GNU awk
可用,我們可以讓awk
找到year
子字符串的索引,然后為我們對輸出進行排序。
樣本輸入:
$ cat animals.txt
1 2 3 4 5 6
123456789012345678901234567890123456789012345678901234567890
alpaca Intermediate Perl 2012 Schwatz, Randal
donkey Cisco IOS in a Nutshell 2005 Boney, James
horse Linux in a Nutshell 2009 Siever, Ellen
在哪里:
year
部分從位置36
到39
一個GNU awk
想法:
awk '
FNR==1 { x=match($0, /[0-9]{4}/) } # find index of the "year" substring in the 1st line of input; assumes the "year" is the 1st occurrence of a 4-digit substring
{ arr[substr($0,x,4)][FNR]=$0 } # populate 2-dimensional array using "year" and row number (FNR) as indexes
END { PROCINFO["sorted_in"]="@ind_num_asc" # sort indexes as numbers in "asc"ending order
for (i in arr)
for (j in arr[i])
print arr[i][j]
}
' animals.txt
這會產生:
donkey Cisco IOS in a Nutshell 2005 Boney, James
horse Linux in a Nutshell 2009 Siever, Ellen
alpaca Intermediate Perl 2012 Schwatz, Randal
如果我們將排序順序從@ind_num_asc
更改為@ind_num_desc
,我們可以按year
降序生成輸出,即:
alpaca Intermediate Perl 2012 Schwatz, Randal
horse Linux in a Nutshell 2009 Siever, Ellen
donkey Cisco IOS in a Nutshell 2005 Boney, James
筆記:
GNU awk
PROCINFO["sorted_in"]
功能需要GNU awk
一種方法是使用sed
將年份復制到每行的開頭,對結果輸出進行數字sort
,然后在每行的開頭刪除年份:
sed 's/^.*[[:space:]]\([12][09][0-9][0-9]\)[[:space:]].*$/\1 &/' animals.txt \
| sort -n | sed 's/^.....//'
問題中帶有示例animals.txt
的輸出是:
oryx Writing Word Macros 1999 Roman, Steven
donkey Cisco IOS in a Nutshell 2005 Boney, James
snail SSH, The Secure Shell 2005 Barrett, Daniel
horse Linux in a Nutshell 2009 Sievers, Ellen
python Programming Python 2010 Lutz, Mark
alpaca Intermediate Perl 2012 Schwartz, Randal
robin MySQL High Availability 2014 Bell, Charles
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.