32515


## 入力データ

次のようなテキストファイルがあるとします。

[code]

    日付  ARTIST  滝廉太郎
    日付  ARTIST  滝廉太郎
    日付  ARTIST  滝廉太郎
    日付  SONG    荒城の月
    日付  ARTIST  滝廉太郎
    日付  ARTIST  山田耕筰
    日付  ARTIST  山田耕筰
    日付  ARTIST  滝廉太郎
    
[/code]

日付のところは日付が入ります（2017年1月10日など）が今回は使用しません。

タブで区切られて次の列は"ARTIST"か"SONG"が来ます。

三番目の列には二番目の列に応じて、アーティスト名か曲名が来ます。

## 欲しい結果

[code]

       5 滝廉太郎
       2 山田耕筰
    
[/code]

このデータから人気のあるアーティストを知りたいと言われたときに、もちろんスクリプト言語などでプログラムを書けば作れますが、30秒でやりたいようなときにはシェルが便利です。

あれこれ調べて工夫したところ

[code]

    cat data.txt | grep -o "\tARTIST\t.*" | sort | uniq -c | sort -nr
    
[/code]

とすることで

[code]

    5   ARTIST  滝廉太郎
    2   ARTIST  山田耕筰
    
[/code]

までは得られました。これで十分な結果ではありますが、"ARTIST"の文字が不要です。

Rubyなどのスクリプト言語では正規表現の一部を()で囲むことでその部分を取り出せますが、コマンドラインのgrepで同じことをするにはどうすればよいのでしょうか？

ちなみに

[code]

    cat data.txt | grep -o "\tARTIST\t.*" | grep -o "ARTIST\t.*$" | grep -o "\t.*$" | grep -o "\S.*$" | sort | uniq -c | sort -nr
    
[/code]

のように何段もgrepを重ねれば

[code]

       5 滝廉太郎
       2 山田耕筰
    
[/code]

にすることはできますが、もう少しシンプルな方法があるのではないかと思い質問してみました。

よろしくお願いします。


CC BY-SA 3.0
2017-02-08T10:31:14.303
32498
2017-02-16T03:20:35.090
14631
question
bash 正規表現 grep
シェルやgrepコマンドなどでデータを集計する方法


> もう少しシンプルな方法があるのではないかと思い

シェルスクリプトではないので回答にはならないのですが、参考までに [q
コマンド](https://github.com/harelba/q)を使う方法などを。

[code]

    $ cat data.txt |
      q -t 'SELECT COUNT(c3) AS nc3, c3 FROM -
            WHERE c2 = "ARTIST" GROUP BY c3 ORDER BY nc3 DESC'
    5   滝廉太郎
    2   山田耕筰
    
[/code]

"Run SQL directly on CSV or TSV files" という説明文の通り、SQL 構文を使って CSV/TSV
フォーマットのファイルから必要なデータを抽出することができます。`c2`, `c3` はそれぞれ 2 番目のカラム、3 番目のカラムに対応するセレクタです。


CC BY-SA 3.0
2017-02-08T11:18:55.450
32500
2017-02-08T11:18:55.450
32498
answer


metropolisさんのコメントでの回答で十分シンプルだと思いますが、grepとcutをawkで済ませる方法もあります。  
`cat data.txt | awk '$2=="ARTIST" {print $3}' | sort | uniq -c | sort -nr`


CC BY-SA 3.0
2017-02-09T00:48:48.767
32515
2017-02-09T00:48:48.767
9820
32498
answer

[code]

    $ sed -n 's/^.*\tARTIST\t//p' data.txt |sort |uniq -c |sort -nr
          5 滝廉太郎
          2 山田耕筰
    
[/code]

`\t` が使えない `sed` もあるので注意。その場合はシェルの種類や設定に依りますが、`\t` の 代わりに Ctrl+v, Tab と打って Tab
文字を入力しましょう。


CC BY-SA 3.0
2017-02-09T13:13:08.070
32535
2017-02-09T13:13:08.070
3061
32498
answer


もしawkに興味がお有りであれば

[code]

    awk '/. ARTIST ./{ary[$3]++}END{for(i in ary){print ary[i],i}}' data.txt |sort -nr
[/code]


CC BY-SA 3.0
2017-02-16T03:20:35.090
32702
2017-02-16T03:20:35.090
20674
32498
answer