キーワード

文字列検索の魔法の杖!情シスのための正規表現 –おつまみとしてのソースコード第13皿

ユニークで面白い、意外なアイデアが詰め込まれているソースコードの世界をおつまみ感覚で紹介するのが、情シスのじかんの「おつまみとしてのソースコード」です!週末も近づき、ちょっと一息つきたくなる木曜日の夕方にお届けしていきます。

大量のログファイル、散らかった設定ファイル、ユーザーからの問い合わせ……。情シスの現場は、つねに「膨大なテキストデータ」と供にありますよね。特に、システム監視やトラブル対応では、テキストデータの大海から必要な情報を探し出すことが求められるケースが多いものです。

「大量のログファイルから特定のエラーだけを抜き出したい」「ユーザーが入力したメールアドレスの形式が正しいかチェックしたい」。そんな時、文字列のパターンを自在に操る魔法の杖、正規表現が大きな武器になります。

しかしながら、「.*」のような簡単な正規表現ならまだしも、複雑な正規表現を使いこなすのは難しい、と思っている方は多いのではないでしょうか?

おつまみとしてのソースコードの第十三回は「情シスのための正規表現」。正規表現は難しそう、と敬遠していた方に向けて、情シスがよく直面するシーンで使える正規表現をピックアップしました。クイズ形式で分かりやすく紹介していきますので、明日から使える実践的なテクニックを身につけましょう!

エンジニア仲間とのアイスブレイクや、一人でまったりする時間のお供に、ぜひご覧ください!

         

正規表現(Regex)とは?

正規表現とは、文字列のパターンを表現するための特殊な文字列です。英語ではRegular Expression、略してRegexとも呼ばれます。

正規表現をひと言でいうと、「複雑な条件の文字列検索を実現する手段」です。通常の文字列検索では、検索したい文字列に一致するものを探す「完全一致」か、検索したい文字を一部に含む文字列を探す「部分一致」が基本的な方法です。しかし、正規表現を使うと、指定した複雑なパターンにマッチする文字列を見つけ出すことができるのです。

例えば、通常の検索では「ERROR」という固定の文字列しか探せませんが、正規表現を使えば「行の先頭が数字で始まり、”ERROR”という単語を含む行」といったパターンを探し出すことができます。

最初はとっつきにくいかもしれませんが、メタ文字と言われる、正規表現で利用される特殊な記号の役割を覚えれば、上記のような文字列検索ができるようになります。

今回ご紹介するクイズで使用する代表的な正規表現を以下にご紹介します。

記号 意味・役割 使用例
. 任意の1文字にマッチする(改行を除く) a.c は “abc”, “axc” などにマッチ
* 直前の文字を0回以上繰り返す ab*c は “ac”, “abc”, “abbbc” にマッチ
+ 直前の文字を1回以上繰り返す ab+c は “abc”, “abbbc” にマッチ(”ac”にはマッチしない)
^ 行の先頭にマッチする ^A は行の先頭が “A” の場合にマッチ
$ 行の末尾にマッチする Z$ は行の末尾が “Z” の場合にマッチ
\d 任意の半角数字1文字にマッチ([0-9]と同じ) \d\d は “00”〜”99″ の2桁の数字にマッチ
[ ]

[ ] 内のいずれか1文字にマッチ

[abc] は “a”, “b”, “c” のいずれか1文字にマッチ
[0-9] 0から9のいずれかの数字1文字にマッチ

[0-9a-f] は16進数の1文字にマッチ

{n,m} 直前の文字がn回以上、m回以下繰り返す

a{2,4} は “aa”, “aaa”, “aaaa” にマッチ

( ) パターンをグループ化する

(ab)+ は “ab” や “ababab” にマッチ

| 「または(OR)」の意味を持つ

こんばん(は|わ)は、”こんばんは”と”こんばんわ”にマッチ

\ メタ文字をただの文字として扱う(エスケープ)

\. は「.」そのものにマッチ

基礎編:パターンマッチングの基本を使ったクイズ

それでは、さっそく情シスの「よくあるシーン」を例に、パターンマッチングを使ったクイズを2つ紹介します!まずは基礎編です。

【基礎編①】正しい電話番号だけを探しだせ!

・お題

与えられた以下のメモから、正しい形式の電話番号だけにマッチする正規表現を作成してください。電話番号はハイフンが入った形式のみを抜き出すものとします。

田中さん 090-1234-5678
山田商事 03-9876-5432
メモ:サーバーAのIPは 192.168.1.10
鈴木課長 08012345678

・解答

\d{2,4}-\d{3,4}-\d{4}

ハイフン付きの電話番号を表現するためには「数字が2〜4桁、ハイフン、数字が3〜4桁、ハイフン、数字が4桁」というパターンを作成する必要があります。そのため、電話番号部分の表現は以下のようになります。

\d{2,4}:市外局番や携帯電話の先頭(2〜4桁)に対応します。
\d{3,4}:市内局番など(3〜4桁)に対応します。
\d{4}:加入者番号(4桁)に対応します。

このパターンにより、ハイフンがない 08012345678 や、IPアドレスは除外されます。正規表現の基本構造を理解する第一歩です。

【基礎編②】ログから必要な情報だけを抜き出せ!

・お題

以下のサーバーログから、”ERROR” または “WARN” で始まる行だけを全て見つけ出してください。

INFO: 2023-10-27 10:00:00 User ‘admin’ logged in.
WARN: 2023-10-27 10:05:12 Disk space is running low.
DEBUG: 2023-10-27 10:05:15 Processing request #123.
ERROR: 2023-10-27 10:10:01 Database connection failed.
INFO: Reported ERROR to administrator.

・解答

^(ERROR|WARN)

このクイズでは、”ERROR” または “WARN”にマッチする行を見つけ出すだけでなく、「この2つの単語のいずれかで始まる」という部分も表現しなければなりません。そのため、以下のように考えます。

^ :「行の先頭」に検索場所を限定します。これにより、行の途中にある Reported ERROR はマッチしなくなります。
 (ERROR|WARN) :「ERRORという文字列、またはWARNという文字列」にマッチさせます。() でグループ化することで、^ の効果が ERROR と WARN の両方にかかるようになります。

これで確実に取得したい行だけを特定することができます。検索が非常に楽になりますね!

応用編:コマンドラインと連携させてより高度な検索を実現

ここからは、実際の業務で使うことを想定し、OSコマンドやgrepなどのコマンドラインツールと組み合わせ、より高度な検索を実現する方法を紹介していきます。

【応用編①】ディレクトリ丸ごと!設定ファイルからIPアドレスを洗い出せ!

・お題

/etc/ ディレクトリ配下にあるすべての .conf ファイルの中から、開発環境でよく使われる「192.168.1.xxx」という形式のIPアドレスが記述されている行を、ファイル名と共に出力してください。

・解答

grep -rE ‘192\.168\.1\.[0-9]{1,3}’ /etc/ –include=”*.conf”

このクイズでは、コマンドラインツールを使って複数のファイルを一気に検索する方法と、数値のパターンマッチング、特殊文字をエスケープする正規表現を使いこなすことがポイントです。

まず、コマンドオプションのポイントを説明します。

grep -r:ディレクトリを再帰的に(サブディレクトリも含めて)検索します。
grep -E:拡張正規表現(|や()などをエスケープなしで使える)を使えるようにします。
–include=”*.conf”:検索対象を .conf ファイルだけに絞り込みます。

次に、肝心の正規表現のポイントです。

192\.168\.1\.:192.168.1. という固定の文字列にマッチします。ドット . は正規表現で「任意の1文字」を意味する特殊文字なので、ただのドットとして扱うために \(バックスラッシュ)でエスケープしているのがポイントです。
[0-9]{1,3}:0から9のいずれかの数字が、1回から3回繰り返す部分(つまり0〜255の数値)にマッチします。これにより、192.168.1.1 や 192.168.1.100 といったIPアドレスを効率よく見つけ出せます。

正規表現とgrepを組み合わせた使い方は、実務で使えるケースが非常に多いため、オプションも含めて覚えておくのが良いでしょう。

【応用編②】ファイル名から特定の命名規則を持つファイルだけをリストアップ!

・お題

ログディレクトリの中から、「YYYYMMDD_access.log」という命名規則に合致するファイルだけをリストアップしてください。(例:20231027_access.log)

・解答

ls /var/log/httpd/ | grep -E ‘^[0-9]{8}_access\.log$’

この問題では、lsコマンドの結果を|(パイプ)でgrepに渡す、コマンドラインの基本テクニックを使います。ここでの正規表現のポイントは、行頭を表す^と、行末を表す$です。

^[0-9]{8}:行頭が8桁の数字で始まる。
_access\.log$:_access.logで行が終わる。

この2つでパターンを挟むことで、「完全に一致するものだけ」を抽出できます。これにより 20231027_access.log.old のような、バックアップファイルが検索結果に混ざるのを防ぐことができます。

正規表現のテスト方法

正規表現の作成・デバッグには、試行錯誤が欠かせません。そこでおすすめなのが、「regex101.com」のようなオンラインテスターです。入力した正規表現がどの部分にマッチするのかをリアルタイムで色付けしてくれます。複雑な応用パターンの検証には必須のツールです。

regex101 (https://regex101.com/

まとめ

いかがでしたか?正規表現は、コマンドラインツールと組み合わせることで、日々の調査や管理業務を効率化する、強力な魔法の杖となります。

最初は複雑で手を出しにくく感じるかもしれませんが、今回紹介した^ $ . | ( ) [ ] { }といった記号を組み合わせるだけで、多くの問題を解決することができます。

ぜひ現場でも、この記事でご紹介した正規表現を参考に、膨大なテキストデータを扱う作業をスマートにこなしていってください!

著者:羽守ゆき
大学を卒業後、大手IT企業に就職。システム開発、営業を経て、企業のデータ活用を支援するITコンサルタントとして10年超のキャリアを積む。官公庁、金融、メディア、メーカー、小売など携わったプロジェクトは多岐にわたる。現在もITコンサルタントに従事するかたわら、ライターとして活動中。
 
 

特集|仕事で疲れた脳みそをリフレッシュ♬
おつまみとしてのソースコード

木曜日の夕方に仕事で疲れた脳みそをリフレッシュしたいとき、一人でゆっくりしたい夜、ちょっとした空き時間に、気軽に「つまめる」ソースコードの話題をお届けします。

まるで隠れ家バーでマスターが語るウンチクのように、普段は見過ごしがちなコードの奥深さや、思わず「へぇ〜!」と唸るようなユニークなアイデア、クスッと笑える小ネタを、ソースコードの世界を熟知した「情シスのじかん」がご紹介します。

コードを書くのが大好きなエンジニアさんも、ソースコードはちょっと苦手…という情シス部門の方も、この特集を読めば、きっとソースコードの新たな一面を発見できるはず。

業務効率化のヒントになるTipsや、セキュリティ対策に役立つ情報も盛りだくさん。

さあ、あなたも「おつまみとしてのソースコード」で、技術の世界をもっと身近に、もっと楽しく感じてみませんか?

本特集はこちら
 

関連記事Related article

       

情シスのじかん公式InstagramInstagram

       

情シスのじかん公式Instagram

30秒で理解!フォローして『1日1記事』インプットしよう!

close close