Command-Line

比較不同文件之間的列

  • September 25, 2015

我有多個文件(大約 20 個文件,30000 行和 32 列),我只需要保留以相同字元串開頭的行。我發現這些案例與我需要的非常相似,但我不知道如何調整它們..

將多個文件(兩個以上)與兩個不同的列進行比較

如何比較兩個不同文件中兩列中的值,回顯差異絕對值<一個小的最大值的整行?

在我的情況下,每個文件都有一個由 12 個字元組成的字元串的第一列,我只需要保留以所有文件中都存在的字元串開頭的行。(每個輸入文件一個文件,或者像上述情況下的一個輸出文件也可以)。我的文件是這樣的:

文件 1

-13  -5   0 19.3769 46.9197   1
-13  -4  -2 347.911 57.7232   1
-13  -4  -1 38.5696 39.0027   1
-13  -4   0 2227.39 124.894   1
-13  -3  -3 113.001 40.2117   1
-13  -3  -2 850.847 78.2881   1

文件2

-13  -5   0 2.19085 50.4632   1
-13  -4  -2 283.628 56.7731   1
-13  -4  -1  41.179 48.6423   1
-13  -4   0 1753.54  125.88   1
-13  -3  -3 28.2363 40.6518   1
-13  -3  -2 562.736 66.0301   1
-13  -3  -1 750.747 77.2795   1

輸出文件1

-13  -5   0 19.3769 46.9197   1
-13  -4  -2 347.911 57.7232   1
-13  -4  -1 38.5696 39.0027   1
-13  -3  -3 113.001 40.2117   1
-13  -3  -2 850.847 78.2881   1

輸出文件2

-13  -5   0 2.19085 50.4632   1
-13  -4  -2 283.628 56.7731   1
-13  -4  -1  41.179 48.6423   1
-13  -3  -3 28.2363 40.6518   1
-13  -3  -2 562.736 66.0301   1

一種方法是首先找到存在於多個文件中的所有 12 個初始字元集:

cut -c-12 file* | sort | uniq -c

上面的cut命令從名稱以 開頭的每個文件中列印前 12 個字元,file然後對這些字元進行排序,並在每行找到的次數後面加上uniq -c。在您的範例文件上執行它會返回:

$ cut -c-12 file* | sort | uniq -c
     1  -13  -3  -1
     2  -13  -3  -2
     2  -13  -3  -3
     2  -13  -4   0
     2  -13  -4  -1
     2  -13  -4  -2
     2  -13  -5   0

因此,除了第一行之外的所有行都出現在兩個文件中。現在,只保留那些出現所需次數的行(在您的情況下為 20 次):

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev

rev簡單地列印它的輸入反轉。我在這裡使用它來計算每行在最後一個欄位中出現的次數。然後將其傳遞給sed它,它被告知僅列印以空格結尾的行,即 20 和 0 或更多空格。這僅保留出現 20 次的行,最終rev將我們帶回原始格式。

您現在可以將整個內容grep作為要搜尋的字元串列表傳遞給:

$ grep -f &lt;(cut -c-12 file* | sort | uniq -c | 
           rev | sed -n 's/ 20 *$//p' | rev) file*
-13  -5   0 19.3769 46.9197   1
-13  -4  -2 347.911 57.7232   1
-13  -4  -1 38.5696 39.0027   1
-13  -4   0 2227.39 124.894   1
-13  -3  -3 113.001 40.2117   1
-13  -3  -2 850.847 78.2881   1

如果您的 shell 不支持該&lt;()格式,您可以將結果保存cut在一個單獨的文件中並使用它,或者只是在循環中執行它:

cut -c-12 file* | sort | uniq -d | 
   while IFS= read -r l; do grep -- "^$l" file1; done

要將每個文件的輸出放在單獨的文件中,請使用:

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev &gt; list
for f in file*; do grep -f list "$f" &gt; "$f.new"; done

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