2016-12-17 58 views
0

給予相同的輸入列表如下:如何隨機排序一個關鍵,而另一個保持與GNU「之類的」原來的排序順序

405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
004:[email protected] 
004:[email protected] 
004:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
005:[email protected] 
005:[email protected] 
005:[email protected] 

(正如你所看到的,第一場是隨機(原始輸入具有數字順序的所有第一個字段,其中004先到達,然後是005,101,405等),但第二個字段按字母順序排列在第一個字符上。)

什麼是期望的是隨機排序,其中第一個字段 - 由冒號「:」分隔,隨機排序,以便在隨機排序過程中第二個字段的所有條目都不重要,所以l因爲所有第一個字段相同的行被分組在一起,但隨機分佈在整個文件中 - 也就是讓第二個字段隨機排序。也就是說,在最終的輸出中,第一個字段中具有相同值的行被分組在一起(但是隨機分佈在整個文件中),而且第二個字段也是隨機排序的。我不能得到這個理想的結果,因爲我不太熟悉排序鍵和什麼。

所需的輸出將類似於此:

405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
405:[email protected] 
004:[email protected] 
004:[email protected] 
004:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
101:[email protected] 
005:[email protected] 
005:[email protected] 
005:[email protected] 

有誰知道如何實現這種類型的排序?

謝謝!

回答

2

你可以很容易地與awk做到這一點。

作爲一個班輪:

awk -F: 'BEGIN{cmd="sort -R"} $1 != key {close(cmd)} {key=$1; print | cmd}' input.txt 

或者碎裂開來,便於解釋:

  • -F: - 設置awk的字段分隔符冒號。
  • BEGIN{cmd="sort -R"} - 在我們開始之前,設置一個變量來執行「隨機排序」。這個在FreeBSD上適用於我。還應該使用GNU排序。
  • $1 != key {close(cmd)} - 如果當前行有比上一個處理不同的第一場,關閉輸出管...
  • {key=$1; print | cmd} - 最後,設置「鍵」變種,並打印當前行,管道輸出通過存儲在cmd變量中的命令。

這個用法利用了一點awk的精彩。當你通過一個字符串(不管它是否存儲在一個變量中)時,該管道在使用時自動創建。您可以隨時關閉它,隨後的使用將重新打開一個新命令。

這個的影響是,每次你close(cmd),你打印當前集隨機排序的行。一旦你到達文件末尾,awk自動關閉cmd

當然,對於這個解決方案的工作,至關重要的是所有具有共享第一個字段的行都被分組在一起。

+0

這當然做到了。能夠看到在'awk'單線程中完成也是令人驚訝的;我在PHP中實現了相同的功能,但是在大約30行代碼中(包括文件讀取,語法檢查等)涉及大量的數組遍歷和混洗。這當然更快,更高效。 – Brendan

+0

儘管我的原始問題,你知道它可能與GNU'sort'嗎?我不這麼認爲,但如果是這樣,我想看看排序語法。 – Brendan

+0

我相當肯定地認爲它不能單獨使用GNU排序。你在你的問題中描述的那種很簡單,就像按照第一個字段分組的簡單隨機化一樣,根本不是一種排序。當涉及到它時,我們只使用GNU排序來在這裏隨機化。你可以用其他的東西替換那個命令 - 'tac'來顛倒每個部分的順序,或者'mailx'發送每個組作爲電子郵件的主體。 – ghoti

1

不是作爲優雅,但不同的方法

$ awk -F: '!($1 in a){a[$1]=c++} {print a[$1] "\t" $0}' file | 
    sort -R -k2 | 
    sort -nk1,1 -s | 
    cut -f2- 

,或者該替代不假定初始分組

$ sort -R file | 
    awk -F: '!($1 in a){a[$1]=c++} {print a[$1] "\t" $0}' | 
    sort -nk1,1 -s | 
    cut -f2- 
相關問題