假設我有一個如此結構化的文件
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/zz/Books/Author-Zigniwe-Hisory-Medicine.pdf
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
我想要一個這樣排序的檔案:
/home/zz/BOOKS/Author-Artemis-Mathematica-Examples.nb
/home/z2/OLDBOOKS1/OLDBOOKS2/Author-Barbero-Lepanto.epub.pdf
/home/zz/AUTHORBOOKS/Author-Chomsky-Who-Rules-the-World.epub
/home/zz/AUTHORBOOKS/Author-Cioran-Il-nulla.epub
/home/z1/OLDBOOKS1/OLDBOOKS2/Author-Watanabe-Waterloo.pdf
/home/zz/Books/Author-Zigniwe-History-Medicine.pdf
即按照字串的字母順序Author-...
正如您所看到的, 的位置Author-...
不是恆定的。
我怎樣才能做到這一點?
答案1
嘗試以下bash
命令:
sort -t- -d -k2 -o output.txt input.txt
它有四個選項加上輸入檔的名稱input.txt
。如果該檔案不在目前目錄中,您必須提供path/to/the/folder/input.txt
.選項及其參數如下:
- -t 標記字段分隔符號。我們使用
-
作為分隔符,以便 之前和之後的所有內容-
都被視為單獨的列。 - -d 表示字典排序。例如,蘋果公司先於貝瑞公司。
- -k2 表示排序所依據的列,在本例中為第二列。請注意,第一列是第一列之前的所有內容
-
。例如,/home/zz/BOOKS/Author
。第二列位於第一列 和第二列 之間-
,即Artemis
。 - -o
output.txt
將排序後的輸出重定向到檔案而不是終端。
希望這可以幫助
答案2
雖然對於當前的例子來說這是多餘的,因為user68186的答案中提出的解決方案,你可以更一般地在 GNU awk 中做這樣的事情:
gawk -F/ '
function mycmp(i1,v1,i2,v2) {
m = split(v1,a);
n = split(v2,b);
return a[m]"" > b[n]"" ? 1 : a[m]"" < b[n]"" ? -1 : 0
}
{
lines[NR] = $0
}
END {
PROCINFO["sorted_in"] = "mycmp";
for(i in lines) print lines[i]
}
' file
請注意,它根據最後一個之後的所有內容的詞彙值進行排序/
- 所以如果格式是Author-<author name>-<title>.<extension>
這樣
- 固定字串
Author-
(沒有任何效果,因為它對所有行具有相同的權重);然後 <author name>-
;然後<title>.
;然後<extension>
這類似於 GNUsort
的簡單 KEYDEF 的-t- -k2
工作方式,即有效的排序鍵從 開始<author name>
並持續到行尾。
在呼叫中省略了明確分隔符split
,以便它們繼承 的值FS
,從而可以輕鬆更改使用不同路徑分隔符的系統。即使檔案名稱是數字,函數""
中附加的空字串也會強制進行詞法比較 - 例如參見mycmp
awk 如何在字串和數字之間進行轉換
如果您願意堅持使用該sort
命令,您可以利用 GNU awk與另一個進程的雙向通信到:
/
複製字串開頭的最後一個分隔字段- 將結果傳遞給
sort
命令 - 讀回排序後的結果,去掉重複的前綴並列印
IE
gawk -F/ '
BEGIN {OFS=FS; cmd = "sort -d"}
{print $NF $0 |& cmd}
END {
close(cmd,"to");
while(cmd |& getline){$1 = ""; print};
close(cmd,"from")
}
' file
這裡有一點作弊,因為絕對路徑(以 開頭的行/
)意味著初始的空白欄位;要處理相對路徑,您需要變更print $NF $0
為print $NF,$0
插入「遺失」分隔符,然後可能使用正規表示式sub()
而不是更簡單的方法$1 = ""
來刪除前導元素。
除了可能比純gawk
解決方案更快/更高的記憶體效率之外,這還允許sort
直接添加其他選項。cmd = "sort -d -t " FS " -k1,1r"
。