朝、はてブを巡回していると購読サイトで以下の記事を見ました。重複行を除外するって頻出パターンだなと。
コマンドで重複行を排除して一度だけ表示する - BioErrorLog Tech Blog
上記の解決方法は以下とのことです。
awk '!seen[$0]++'
例えば、「cat a | awk '!seen[$0]++'」という感じにすると重複行が除外されます。すげー。ブログエントリーでは解説もしてくれています。
seenというのは連想配列として使っているらしいんですね。。。awkって必要になったときに調べて使ってきたので知識といってもつまみ食い状態でした。
重複行を除外するといえばuniqコマンドが思いつきます。ただ、これは隣り合う行が重複していなければならないので一旦ソートしなければならないですね。sort a | uniqという感じ。でも、これだと内容が変わってしまいます。それがないというメリットですね?たぶん。
ちなみにseenって変数名ってことは別に何でもいいことになりそうと想像。試しにやってみると以下でも動作しました。
awk '!x[$0]++'
さらに以下でも動作しました。
awk '!_[$0]++'
面白い。
あれ?$0ということは$1や$2もいけるよなぁ。。。とか。例えば、aの内容を以下のようにしてみました。空白区切りです。
1 2 5 1 3 6 1 4 6
で、cat a | awk '!_[$1]++' とやると以下でした。最初のデータが同じものは出力されません。なるほど。
1 2 5
なので、当然、cat a | awk '!_[$2]++' やると以下になりました。第2項はすべて異なりますので。
1 2 5 1 3 6 1 4 6
さらに、cat a | awk '!_[$3]++' やると以下になりました。何に使えるかわかりませんが。。。
1 2 5 1 3 6
ということは否定しなければどうなるんやろ?cat a | awk '_[$1]++ ' えーと。2個目以降が出現したときに出力されます。
1 3 6 1 4 6
変数が使えるなら論理演算だっていけるよね、といことで cat a | awk '!_[$1]++ || !_[$3]++' と書いてみると。はぁ。。。確かにそうなる。
1 2 5 1 3 6
cat a | awk '!_[$1]++ && !_[$3]++' だとこうなりますわね。。。
1 2 5
何に使えるかわかりませんが。。。何となく想像するのは例えば、ログファイルがあってそのログファイルをフィルタリングするときに、同一IPアドレスからあるページにアクセスがあったときの初回のアクセスを取り出したいとか?でしょうか。
そもそも実務でファイルを直接フィルタリングしたい状況って現在ではもうないかもですが。
朝の手遊びでした。
面白い(かつ有益な)情報ありがとうございました。
こうやって自分で遊んでみると自分のスキルになるんですね。。。見てるだけだと明日には忘れるはずですので。