【Sed活用講座】 Csvデータから特定の文字列を含む行を抽出する


2020/04/06

特定の文字列を含む行を抽出するという操作は、シェルスクリプトのプログラムパターンにも割と頻繁に目にします。

CSV形式のデータで、何番目かはっきりした特定の列で、対象とした文字列を含むかを判定するのはAwkとJqで実装するのは比較的容易ですが、不特定で複数の行(もしくは複数のセル)の中で、対象の文字列を含むような曖昧さのある場合には、AwkかJqで処理するには少し冗長な操作になるときがあります。

合同会社タコスキングダム|蛸壺の技術ブログ

ということで、今回は先にSedで特定の文字列を含む行をフィルタリングのやり方を、AwkかJqで利用する前の下処理の方法として紹介します。


はじめに

当サイトではオフィス業務のComputer-Aidedなハイブリッドな方法を模索し、より効率的なExcel業務を実現したい多忙なオフィスワーカー向けの主にAwkとSedを使うシェル講座です。

シェルスクリプトはどこでもどんなOSでも基本的に使えて、しかも一度使い方を覚えると、Excelと組み合わせて最高に効率の良いオフィスワークツールが作れることでしょう。

合同会社タコスキングダム|蛸壺の技術ブログ


Sedで行全体を検索&フィルタリング

列の区別をせずにとりあえず対象とするパターンを含む行をファイル全体から絞り込む操作は、データファイルの容量が巨大になってくるほど重要性を増してきます。

例えば以下のような好きなお寿司のアンケート調査のデータを集計していたとしましょう。

            
            山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
        
例えばここから回答結果にイカと答えた項目を抽出したいとすると、Sedスクリプトのpコマンドを利用することで、パターンでマッチした行のみを抽出できます。

            
            $ sed -n -r '
/貝|イカ/p
' <<EOF
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
EOF
#👇出力
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
        
とご覧のように拡張正規表現(-rオプション)を使って/パターン/にマッチした行を全て表示することができました。

Sedのpコマンドは今回のような操作に対して強力に使えるのですが、pコマンドの利用とセットに利用されるのが
-n/--quietオプションです。もし、この-nオプションがない場合はどうなるかというと、

            
            $ sed -r '
/貝|イカ/ p
' <<EOF
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
EOF
#👇出力
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
        
...フィルタされるどころか、なんだか行自体が増えてしまいました。

pコマンドの本来の機能は現在のパターンスペースを出力する、というものです。ですがSedのデフォルトではパターンスペースは常時出力されることになっているので、-nオプションなしの上のスクリプト例ではデフォルトの出力とpコマンドの出力が二重になって出てきてしまったようです。

ということで-nオプションは、
デフォルトのパターンスペースの出力を抑制するというオプションですので、何かもし行のフィルタリングが上手く行かない場合には、-nを指定しているかをまず確認しましょう。

パターンの否定

もし、先ほどのケースとは逆にら回答結果に貝とイカと答えなかった人たちを抽出する場合のSedスクリプトも簡単な修正で可能です。

            
            $ sed -n -r '
/貝|イカ/ ! p
' <<EOF
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
吉岡 マダ郎,アジ,赤貝,大トロ,アナゴ,サバ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
真中 ポニ太,タコ,とびっこ,マグロ,イワシ,つぶ貝
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
安藤 クゥ弘,甘エビ,赤貝,サーモン,アナゴ,タイ
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
時山 バフ丸,アナゴ,サバ,ヤリイカ,白子,タイ
EOF
山田 モフ雄,ボタンエビ,サーモン,マグロ,アジ,甘エビ
川北 ザマ麿,エンガワ,ハマチ,イワシ,ウニ,マグロ
西下 ガサ美,カンパチ,サバ,サーモン,エビ,とびっこ
神崎 ルギ子,サーモン,アナゴ,ウニ,中トロ,たまご
風間 フッ松,ハマチ,アジ,カンパチ,中トロ,あん肝
        
このスクリプトではpコマンドの手前にフィルタ結果『ではない』と否定を意味する!コマンド追加することで、貝かイカのどちらも回答しなかった行の項目だけを出力しています。


まとめ

今回は簡単にSedコマンドを使った行全体に渡るスクリーンニングの方法を紹介しました。このテクニックはAwk/Jqによる集計操作の前処理として良く利用するので、後日、集計するスクリプトの特集をする際にたびたびお目にかけると思います。
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。