2004年6月20日

計算檔案中重覆的行數

因為發現負責提供服務的系統中,似乎有人在暴力測試用戶的資料,好在之前有對系統使用狀況進行 Log 登載,所以嘗試實施統計那些作業編號有人在惡搞。

首先,Linux 上的確有計算重覆行數的指令:uniq -c ,但這個指令有所限制:只能計算 連續相同 的部份。

ada@www tmp $ uniq --help
用法:uniq [選項]… [輸入 [輸出]]
將 <輸入> (預設為標準輸入) 的資料中每行連續相同的資料捨棄至只剩一行,
並在 <輸出> 顯示結果 (預設會在標準輸出顯示結果)。
長選項必須用的引數在使用短選項時也是必須的。
  -c, --count           每行前加上出現次數
  -d, --repeated        只印出重覆的資料
  -D, --all-repeated[=分隔方式]
                        印出所有重覆的資料
                        分隔方式={none(預設)、prepend、separate}
                        會使用空行來分隔資料。
  -f, --skip-fields=N   不比較最初的 N 個欄位
  -i, --ignore-case     比較時忽略大小寫
  -s, --skip-chars=N    不比較最初的 N 個字元
  -u, --unique          只印出沒有重覆的資料
  -w, --check-chars=N   每行比較不多於 N 個字元
      --help     顯示此求助說明並離開
      --version  顯示版本資訊並離開

一個欄位是由一組空白字元加上一組非空白的字元組成的。 當同時指定略過欄位和略過字元不作比較時,會先略過欄位。

請向 <bug-coreutils@gnu.org> 回報錯誤。

即然 uniq -c 必須要連續相同的資料行才視作重覆,那麼只要排序一下不就好了?這個指令是 sort !

ada@www tmp $ sort --help
用法:sort [選項]… [檔案]…
將所有 <檔案> 內容合併和排序,並在標準輸出顯示結果。

排序選項:

長選項必須用的引數在使用短選項時也是必須的。 -b, --ignore-leading-blanks 忽略每行開始的空白字元 -d, --dictionary-order 只考慮空白字元、英文字和數字 -f, --ignore-case 排序前先將小寫字元轉換為大寫 -g, --general-numeric-sort 以普通數值的方式作比較 -i, --ignore-nonprinting 只考慮可列印的字元 -M, --month-sort 比較月份: (不明) <‘JAN’< … <‘DEC’ -n, --numeric-sort 將字串轉換為數值來作比較 -r, --reverse 以相反的次序排列

其它選項:

-c, --check 只檢查輸入資料是否排列好,不會真正將資料排序 -k, --key=位置1[,位置2] 排序索引由 <位置1> 的欄位開始,在 <位置2> 的 欄位結束 (1 表示第一個欄位) -m, --merge 只合併已經排序的檔案;不分別排列每個檔案的內容 -o, --output=FILE 將結果寫入 <檔案> 而並非在標準輸出顯示 -s, --stable 不進行最後的整行比較排序 -S, --buffer-size=大小 指定記憶緩衝區的 <大小> -t, --field-separator=SEP use SEP instead of non-blank to blank transition -T, --temporary-directory=DIR use DIR for temporaries, not $TMPDIR or /tmp multiple options specify multiple directories -u, --unique with -c: check for strict ordering otherwise: output only the first of an equal run -z, --zero-terminated 以位元組 0 而非 newline 字元作為每行的結束字元 --help 顯示此求助說明並離開 --version 顯示版本資訊並離開

<位置> 的格式是 F[.C][OPTS],其中 F 是欄位編號,C 是該欄的字元位置。OPTS 是一個或多個單字元的排序選項,這些專用的選項會取代該排序索引的一般排序 選項。如果沒有指定排序索引,則以整行的內容作為索引。

<大小> 可以加上如下的單位: %% = 1%% 記憶體,b=1,K=1024 (預設值),還有 M、G、T、P、E、Z、Y 如此類推。

如果沒有指定 <檔案> 或 <檔案> 是 -,則由標準輸入讀取資料。

*** 警告 *** 和語系有關的環境變數會影響排序結果。 如果要以位元組數值作為排列次序,請設定環境變數 LC_ALL=C。

請向 <bug-coreutils@gnu.org> 回報錯誤。

所以結論很簡單了,假設有一文字檔內容如下:

ada@www tmp $ cat text.txt
11111
22222
33333
44444
22222
44444
11111
11111
33333
55555
44444

若要計算重覆的資料行數,可以下指令:

ada@www tmp $ sort text.txt | uniq -c
      3 11111
      2 22222
      2 33333
      3 44444
      1 55555

透過 Linux 上即有工具的簡單組合,可以減損眼力的消耗和時間的浪費,提供各位做一個參考!