user_idを含むログファイルと、コンテスト結果を含む他の列があります。私の考えでは:
- すべての勝利したユーザーのuser_idを探す
- これらの user_id が与えられると、そのユーザーのすべてのログエントリが返されます。
例:
log.csv
id,user_id,winner,page_id
1,user_1,win,1
2,user_1,,10
3,user_2,,1
4,user_2,,2
5,user_4,win,10
6,user_5,,2
7,user_5,win,3
このようなログファイルがある場合は、現在これを2つのステップに分割します。
ステップ1:「win」という言葉が言及されているすべての行を返します。
/win/ {
FS=","
# To make unique, store user_id's in array
n[$2] = 0
}
# Print the unique array keys
END{
for (x in n)
print x
}
これは以下を生成します。
user_1
user_4
user_5
この出力をファイルに保存します。output.txt
次に、そのファイルと元のログファイルを別のawkファイルに渡します。
NR == FNR{
n[$1] = 0 # Set the user ID to the array
next # Go to the next file
}
{
FS=","
if($2 in n){
print $0
}
}
これは正しい出力を返します(各user_idのすべての勝利行)。
1,user_1,win,1
2,user_1,,10
5,user_4,win,10
6,user_5,,2
7,user_5,win,3
これを行うよりエレガントな方法はありますか?単一のawkファイルを使用しますか?
答え1
遅すぎましたが、子孫のために次のようにできることをお知らせしたいと思います。
awk '
{
# do first pass stuff
}
END
{
while(getline < FILENAME)
{
# do second pass stuff
}
close(FILENAME)
}
' file
より多くのパスを実行するには、close(FILENAME)
最初のwhileループの後に2番目のループを実行できます。
答え2
2つの配列を使いましょう。
awk -F, '{a[$0]=$2;if($3=="win")b[$2]++}END{for(i in a){if(b[a[i]])print i}}'
答え3
これを行うよりエレガントな方法はありますか?
もちろんです。タイトルで述べたように、同じファイルに対してAwkを2回実行するだけです。
awk -F, '$3=="win"{won[$2]} FNR==NR{next} $2 in won' log.csv log.csv
答え4
私の埋め方はあなたが持っているgrep
よりも速いです。awk
GNU grep
Perl拡張あなたは試すことができます
fgrep -f <(grep -oP "[^,]*(?=,win)" log.csv) log.csv
それ以外の場合は、出力をパイプする必要がperl.ext
あります。grep
cut
fgrep -f <(grep win log.csv | cut -d, -f2) log.csv
または使用してくださいsed
(上記より少し速いようですgrep
| cut
)
fgrep -f <(sed -n '/win/s/^[^,]*,\([^,]*\).*/\1/p' log.csv) log.csv