あるファイルから別のファイルのパターン発生回数を計算するエレガントな方法

あるファイルから別のファイルのパターン発生回数を計算するエレガントな方法

2つのサンプルファイルがあるとしましょう。最初のファイルは、名前の最初の2文字と姓の最後の2文字を組み合わせて作成された一意の従業員名で埋められます。Example : Peter Smith - Peht

最初のファイルには以下が含まれます。

Peht
Mawo
Stso
Makr
Bavo

2番目のファイルには、システムにログインした時間の履歴が含まれています。 (明らかにリストにないスタッフもいますfile1。)

2番目のファイル:

Mawo 21.4.2016 17:49
Peht 21.4.2016 17:58
Mawo 22.4.2016 7:58
Wato 22.4.2016 7:59
Stso 22.4.2016 8:02
Bavo 22.4.2016 8:15
Bane 22.4.2016 9:01
Bavo 23.4.2016 9:12
Mawo 23.4.2016 9:24
Dalo 23.4.2016 9:54
Peht 23.4.2016 9:58
Grma 24.4.2016 10:00

file1の従業員がシステムに何回接続したかを調べる必要がありますfile2

最良のアプローチは何ですか?私が考えることができる唯一の解決策は、2つのループを実行することです。ループ内の各名前に対して名前が一致するかどうかを尋ねてくださいfile1。可能であれば、誰かが私にこの問題を解決するための優雅な解決策を与えることができますか?file2grepcount++awk

答え1

次の簡単なもの:

mapfile -t names < file1
for name in "${names[@]}"
do
  echo "${name}" $(grep -c "^$name " file2)
done

次の出力を提供します。

Peht 2
Mawo 3
Stso 1
Makr 0
Bavo 2

grep stringは、行の先頭(^)にユーザー名を固定し、行の後にスペースを強制することを意味します。

答え2

テスト.awk:

FNR == NR{ 
  names[$1]
  next
}   
($1 in names){
  ulog[$1]++
}   
END{
  for(name in ulog){
    print name ":" ulog[name]
  }   
}   

次のように実行します。 awk -f test.awk user.list user.log

FNR==NR # ファイルレコード番号 == レコード番号、もしそうなら、それはまだ最初のファイルにあります。

next# まだ最初のファイルにあるので、残りはスキップして次の行を取得します。

残りは自明でなければなりません。

または一行で

awk 'FNR == NR{ names[$1]; next } ($1 in names){ ulog[$1]++ } END{ for(name in ulog){ print name ":" ulog[name] } }' user.list user.log

答え3

//joinを実行する別の方法は次のとおりです。sortuniq

join  -1 1 -2 2 -a1 -e "0" -o 1.1 2.1 <(sort file1) \
<(cut -d' ' -f1 file2 | sort | uniq -c)

デフォルトでは、名前をUE名file1uniq関連付けて、file2使用0中の不足しているフィールドに基づいて計算しますfile2


私はawk次を実行します:

awk 'NR==FNR{s[$1]++;next}
{if ($1 in s) {print $1, s[$1]}
else {print $1, 0}}' file2 file1

まず read を実行しfile2、各名前の発生回数を数え、次にfile1各名前の個数を読み込んで印刷しますfile2(またはfile2名前がその名前にない場合は 0 を印刷します)。

関連情報