今回も文字列検索では定番のgrepです。今回は日本語等での検索を行ってみます。


前回同様にデスクトップのsampleディレクトリにサンプルとなるテキストファイルを入れておきます。また、カレントディレクトリはsampleディレクトリとします。コマンドならcd ~/Desktop/sampleと入力します。

○macOSへの対処

 macOSの場合、デフォルトでインストールされているgrepでは手軽に日本語や漢字など様々な文字にマッチさせるのが大変(面倒)です。そこでHomebrewを使ってGNU版のgrepをインストールして使うのがよいでしょう。なお、インストールするとコマンド名はgrepでなくggrepになります。以下の説明でgrepのコマンド名をggrepに置き換えて実行してください。
 Homebrewをインストールしていない場合は以下のURLにアクセスしてインストールしてください。

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

以下のようにしてGNU版のgrepをインストールします。

brew install grep

以下のコマンドを入力してインストールされたか確認します。この場合、バージョンが表示されます。

ggrep -V

○日本語にマッチ

 それでは日本語にマッチする処理をやってみましょう。
ここまでは英語でマッチする例ばかりでした。こういう正規表現のマッチパターン例では、ほとんどが英語になるのも仕方ないのかもしれません。英語圏の文字は基本的に1バイトで表現されますが、日本語や中国語などは2バイト以上のマルチバイトで表現されます。おまけに日本語などマルチバイトでは文字をどのように示すかのコードが複数あります。日本語なら過去にはJIS、一番多く使用されていたShift JIS、そしてUNIX系で使われていたEUCがあります。今は文字コードが複数混雑していた時代からUnicodeに統一されました。が、Unicodeもなかなか複雑です。とは言え絵文字の普及にともなって、かなり改善されたはずなので、ここからは日本語のマッチについてトライしてみましょう。また、仮名と濁点は分離されていないものとします。(NFC(Normalization Form Canonical Composition)の状態とします)
 また、2000年より前のテキストの場合、文字コードはShift JISやEUCの可能性があります。そのようなテキストデータを扱う場合はnkf,iconvなどで文字コードをUnicodeに変換してからgrepでマッチさせる方がよいでしょう。
○日本語1文字/絵文字にマッチ

 まず簡単なところで日本語/絵文字の1文字だけにマッチさせてみましょう。
ここで使用するテキストファイル(sample1.txt)の内容は以下のようになっています。

sample1.txt

Sample Text (Alphabet only)
この行は平仮名と漢字とカタカナが混在しています。
ここは、ひらがなのみです
ココハカタカナダケ
~やーなどの記号です
漢字文化圏

이 문장은 한글 문자로 쓰여 있습니다.
هذه الجملة مكتوبة باللغة العربية.

 「す」の1文字にマッチするには以下のように指定します。

grep 'す' sample1.txt

マッチする文字がない場合は何も出力されません。

grep 'ん' sample1.txt

絵文字にマッチさせるのも同様に指定できます。

grep '' sample1.txt

○単純な日本語文字列にマッチ

 次に日本語文字列にマッチさせてみましょう。ここでは、文章中に含まれる「です。」の文字にマッチさせます。この場合は単純にgrepの文字列として指定するだけです。ここらへんは英文字の場合と変わりません。それぞれのテキストファイルの内容は以下のようになっています。

sample2a.txt

今日はいい天気ですね。
明日も晴れです。

明後日は雨の予報。

sample2b.txt

今日はいい天気だ。
明日は晴れだ。
明後日は雨の予報である。

ここで「です。」にマッチさせる場合は以下のようになります。ですます調から断定調になっているかどうか確認する場合に使えます。

grep 'です。' sample2a.txt

grep 'です。' sample2b.txt

平仮名/片仮名だけでなく漢字にもマッチできます。

grep '天気' sample2a.txt

明日や明後日のように明と日で囲まれた文字(範囲内は漢字)にマッチさせる場合は以下のようになります。

grep -P '明[一-龯]*日' sample2a.txt

○平仮名にマッチ

 次に平仮名にマッチさせてみましょう。平仮名は以下のように指定します。


grep -P '\p{Hiragana}' sample1.txt

 ただし、この指定方法だと句読点などにもマッチしてしまいます。句読点は除外したい場合は以下のように指定します。

grep -P '(?![・ー、。ー~])\p{Hiragana}' sample1.txt

○片仮名にマッチ

 次に片仮名にマッチさせてみましょう。片仮名は以下のように指定します。

grep -P '\p{Katakana}' sample1.txt

 ただし、この指定方法だと句読点などにもマッチしてしまいます。句読点は除外したい場合は以下のように指定します。

grep -P '(?![・ー、。ー~])\p{Katakana}' sample1.txt

○漢字にマッチ

 次に漢字にマッチさせてみましょう。漢字は以下のように指定します。なお、ここでの漢字は日本語圏での漢字だけでなく簡体字・繁体字なども含まれます。

grep -P '\p{Han}' sample1.txt

 ただし、この指定方法だと句読点などにもマッチしてしまいます。
句読点は除外したい場合は以下のように指定します。

grep -P '(?![・ー、。ー~])\p{Han}' sample1.txt

○ハングルにマッチ

 ハングル文字にマッチさせたい場合は以下のように指定します。

grep -P '\p{Hangul}' sample1.txt

 ただし、この指定方法だとなぜか日本語の句読点などにもマッチしてしまいます。句読点は除外したい場合は以下のように指定します。

grep -P '(?![・ー、。ー~])\p{Hangul}' sample1.txt

○各国語にマッチ

 各国語にマッチする指定方法を以下に示します。

例えばアラビア語にマッチさせたい場合は以下のように指定します。他にもいろいろ指定して試してみてください。

grep -P '\p{Arabic}' sample1.txt

grepは昨今のように多国語が入り乱れてくると、なかなか期待通りにマッチさせるのが難しくなってきます。そんな場合は、AIを使ってパターンマッチする部分を生成してもらえばよいでしょう。

それでは、また次回。
編集部おすすめ