特定のフレーズがファイルに表示される回数を数え、きちんと書式設定するにはどうすればよいですか?

特定のフレーズがファイルに表示される回数を数え、きちんと書式設定するにはどうすればよいですか?

データを抽出するログファイルがあります。特定のモジュールがチェックインおよびチェックアウトされると、次の形式とリストがあります。

19:50:26 (license_manager) OUT: "certain_module" [email protected]
19:50:28 (license_manager) IN: "rarely_used_module" [email protected]
19:50:28 (license_manager) IN: "certain_module" [email protected]
19:50:28 (license_manager) IN: "different_module" [email protected]
19:50:38 (license_manager) OUT: "certain_module" [email protected]
19:50:38 (license_manager) OUT: "different_module" [email protected]

これまでのところ、私は以下を持っています。私は「rarely_used_module」がいつ確認されるのか、そして誰が確認するのか特に興味があります。

cd /path/to/script && cat logfile.txt | grep -c "rarely_used_module" 

しかし、これは私にカウントだけを提供し、他に何もありません。私は2つの理由でこれをより複雑にしたいと思います。シェルスクリプトの詳細を学び、スクリプトでより多くのbash概念を実装するために、2番目にライセンスがチェックアウトされた時期とどのユーザーが検索したかを知らせることができます。それ。

最も理想的な方法は、このライセンスがチェックアウトされた回数を数え、参照用に一種の表にフォーマットすることです。可能ですか?

アップデート#1

希望の出力は以下の通りです。以下では、ほとんど使用されていないモジュールが2人のユニークユーザーによって4回、個別に2回チェックアウトされた理論的な例を示します。

Number of license checkouts for rarely_used_module: 4 
User : [email protected] (2)
User : [email protected] (2)

デフォルトでは、モジュールがチェックアウトされた合計回数とライセンスをチェックアウトしたユーザーの名前が必要です。 "rarely_used_module"のOUT:行をキャッチできることを知っていますが、それを処理する方法がわかりません。

答え1

更新された質問の場合:

awk '
/"rarely_used_module"/ && /OUT:/ { nc[$NF]++ ; c++ }
END {
    printf "Number of license checkouts for rarely_used_module: %d\n", c
    for (i in nc) printf "User: %s (%d)\n", i, nc[i]
}
' logfile.txt

次の出力を生成します。

Number of license checkouts for rarely_used_module: 4
User: [email protected] (2)
User: [email protected] (2)



要件が増えた場合にコードを拡張する方法を示すために、元の答えを以下に残しました。

以下は、次を使用してこれらのタスクを実行する方法の例ですawk

awk '
BEGIN { SUBSEP = ", " ; OFS = ": " }
{ m[$(NF-1)]++ }
{ n[$(NF-1)] = n[$(NF-1)] " " $NF }
{ nc[$(NF-1),$NF]++ }
END {
    print "\n=== count modules:"
    for (i in m) print i, m[i]
    print "\n=== collect names using modules:"
    for (i in n) print i, n[i]
    print "\n=== count names using modules:"
    for (i in nc) print i, nc[i]
}
' logfile.txt

説明する:

  • { m[$(NF-1)]++ }- 入力データの2番目のフィールド(モジュール)のカウンタをインクリメントします。
  • { n[$(NF-1)] = n[$(NF-1)] " " $NF }- 各キー(モジュール)の最後のフィールド(名前)をリンクします。
  • { nc[$(NF-1),$NF]++ }- (名前、モジュール) キータプルのカウンター増加

サンプルデータを使用すると、次の出力が生成されます。

=== count modules:
"rarely_used_module": 1
"different_module": 2
"certain_module": 3

=== collect names using modules:
"rarely_used_module":  [email protected]
"different_module":  [email protected] [email protected]
"certain_module":  [email protected] [email protected] [email protected]

=== count names using modules:
"different_module", [email protected]: 1
"different_module", [email protected]: 1
"certain_module", [email protected]: 2
"rarely_used_module", [email protected]: 1
"certain_module", [email protected]: 1

答え2

すべての行を変更または一致させるよりも複雑なものが必要な場合は、Pythonは汎用言語なので使用します。awk(btw、Python awkがあります)よりも冗長かもしれませんが、pawkよく文書化され、簡単に拡張できるコードも提供します。

以下は、タスクに適したPython 2スクリプトです。

from collections import defaultdict

FILE = 'module.txt'

# Global table of usages is 
# dict [ module_name ] -> dict [ user_name ] -> count
usage = defaultdict(lambda : defaultdict(int))

# Read, parse data and add usage count where needed
with open(FILE) as f:
    for line in f:
        # Split using spaces and pick last 2 fields, 
        # strip unncessary characters
        fields = line.split()     
        user = fields[-1].rstrip()
        module_name = fields[-2].strip('"')

        usage[module_name][user] += 1

# Now print pretty results
for module_name, module_usage in usage.items():
    print '====> ', module_name
    for user, count in module_usage.items():
        print '\t', user, count

サンプルについて、次のデータが印刷されます。

====>  different_module                                                                                                                                                        
        [email protected] 1
        [email protected] 1
====>  rarely_used_module
        [email protected] 1
====>  certain_module
        [email protected] 2
        [email protected] 1

関連情報