【業務効率改善】正規表現のススメ
こんにちは。
クラウドソリューショングループのsatokです。
今回は、様々な業務で何度もお世話になった「正規表現」について書いていきます。
単純作業からコーディングまで、幅広く使用するシーンがあるので是非ご覧ください。
目次
1.この記事の目的
この記事では、業務効率改善に繋がる正規表現をご紹介します。
「正規表現って何?」という方向けの内容となっておりますので、「普段の業務にかかる時間を少しでも減らしたい」と感じている方への何か助けになれば幸いです。
2.正規表現とは
そもそも正規表現とは何か、という点について簡単にご説明します。
正規表現とは「文字列を検索などする際に使える表現の一種」です。
具体例を出して説明します。
例えば、あるファイルから「ショートカット」という単語を検索したいとき、そのまま「ショートカット」という単語を検索するのは簡単です。
ここで「【ショー】から始まるあの単語なんだっけ」となった際に役立つのが正規表現です。
このように、正規表現は「普段より少し幅広く検索できる」ようにする表現と言えます。
3.具体例
ここからは具体的にどのような表現があるのかを見ていきます。
序盤は基礎的なものから始め、段々と組み合わせや複雑なものを紹介します。
以下、正規表現を表す際には【】で囲みます。
【.】 : 任意の1文字を示す
まずは基礎です。
【.】(ドット)は任意の1文字を表すことができます。
例えば、【き.く】という正規表現は、【きかく】や【きさく】、【きはく】など【き[何か1文字]く】のすべてのパターンを表します。
この【.】を用いて曖昧に表現することが正規表現のすべての始まりと言っても過言でははないため、覚えておいてください。
【*】 : 直前の表現を0回以上繰り返す
【*】があるすぐ前の表現を0回以上繰り返したものを表します。
例えば【すも*】という表現は【す】、【すも】、【すもも】、【すもももももももも】などを表します。
ここで注意しなければならないのは「0回以上の繰り返し」のため、「も」が1度も現れない場合も表せるという点です。
【+】 : 直前の表現を1回以上繰り返す
こちらは先ほどの直前のものと異なり、少なくとも1回以上繰り返します。
つまり【すも+】という表現は【すも】、【すもも】、【すもももももももも】などを表します。
【{n}】 : 直前の表現をちょうどn回繰り返す
ここまでの表現では、沢山繰り返す場合や、何回繰り返すかわからない場合に使用するものでしたが、この表現では回数を指定することができます。
例えば、【すも{4}】という表現は【すもももも】を表します。
【{n,m}】 : 直前の表現をn回以上m回以下繰り返す
1つ前の表現では「ちょうどn回」しか表すことができませんでしたが、こちらの表現では回数に幅を持たせることができます。
例えば、【すも{2,4}】という表現は【すもも】、【すももも】、【すもももも】を表します。
また、この表現は後ろの数字を省略することができ、【{n,}】と書くこともできます。
この場合は「n回以上」という表現となります。
よって、【すも{2,}】という表現はすも】、【すもも】、【すもももももももも】などを表すということになります。
【[]】 : []内の文字のうちの1つ
【.】は任意の1文字を表すことができましたが、場合によっては「あ、い、う、のどれか」や「数字のみ」検索したい状況もあると思います。
そのような場合に使用するのが【[]】です。
例で出した「あ、い、う、のどれか」という表現は【[あいう]】で表すことができます。
また、例で出した「数字のみ」という表現は【[0123456789]】、もしくは【[0-9]】で表すことができます。(あまりにも見づらかったため、この画像のみ明るさを調整しております。)
【[]】内での表現として、「【-】でつないだものはその左右の間のものも全て含んだ表現」として扱われます。
例えば「2から6だけ表したい」場合は【[2-6]】となりますし、「”あ”から”そ”まで表したい」場合は【[あ-そ]】となります。
ここで、左右の表現は文字コードの順番に依存しているため、【[あ-そ]】と書くことはできても【[そ-あ]】と書くことはできませんので注意してください。
【[^]】 : []内の文字以外の1つ
1つ前のセクションで紹介したものの、カッコ内の先頭に【^】を入れると、論理否定のようにマッチします。
例えば、【[^a]】は「a以外の1文字」を表し、【[^あいうえお]】は「あ~お以外の1文字」を表します。
なので、1つ前のセクションと組み合わせることで「数字以外」=【[^0-9]】や「aからjまでのアルファベット以外」=【[^a-j]】といった表現をすることも可能です。
【^】 : 行の先頭から
【^】は表現の開始位置が行の先頭からであることを表します。
例えば、【abc】と書く場合は、「abcという文字列」であればどこにあっても表現できますが、【^abc】と各場合は、「行の先頭のabcという文字列」のみを表現します。
【()】 : ひとまとまりにする
これまでの表現は「ある文字が特定の回数繰り返す」場合を表すことができましたが、「2文字以上が特定の回数繰り返す」場合は表せませんでした。
そこで使用するのが【()】です。
例えば、【(もも){2}】は「もも」が2回繰り返される、すなわち「もももも」という文字列を表します。
また、【(もも)+】と書けば、「もも」が1回以上繰り返される場合を表すことができます。
【()】/【$1】 : 記録して置換する
【()】にはもう1つの使い方があります。
それは、「置換する際に、置換前の文字列を再び使用する」ことです。
「置換って何?」という方はこちらの記事をご確認いただければと思います。
置換を行う際に、「特定の文字列の一部分のみを変更したい」となった際にこちらの表現が使用できます。
例えば、特定のドメインのメールアドレスのみ、アドレス部分を別の文字列に置換したいとします。
今回は「@male.jp」というドメインのアドレスの先頭に「#deleted#」という文字列を追加します。
この場合は以下のような表現で置換することで実現できます。
置換前: 【^([^@]+@male.jp)】
置換後: 【#deleted#$1】
置換前の表現について詳しく見てみましょう。
まず【^】から始まり全体が【()】で囲まれています。
つまり、「先頭から当てはまる部分全てを記録する」という表現になっています。
【()】の中を見ると、まず【[^@]+】という表現が来ています。
【[]】の中は【^@】となっているため、【[^@]】は「@以外の任意の文字」を表します。
よって、【[^@]+】で「@以外の任意の1文字以上」を表します。
その後ろに【@male.jp】が来ることで、【()】内全体として「@以外の1文字以上+@male.jp」を表すため、「@male.jp」で終わる文字列を表すことができます。
したがって、これらが$1に記録されるため、置換後は「先頭に#deleted#を追加したアドレス」を表します。
ここで、「【^(.*@male.jp)】でもいいんじゃないか」と思う方もいらっしゃるかと思います。
結論としては、今回はどちらの表現でも問題ありません。
しかし、今回使用した方法のように「特定の文字以外を使用している文字列」を検索、置換するシーンは多々あります。
特に、「csvファイルの4番目の要素」を指定する際に、【^([^,]*,){3}([^,]*,)】といった表現を用います。(この表現の解説は割愛しますが、理解できれば初心者は卒業と言えるでしょう)
要するに、「特定の文字列で区切られるもののn番目」を指定したい際などに用いられる、という意味です。
応用する際に自由度がかなり違うため、是非こちらの表現も覚えていただきたいと思います。
また、「先頭の【^】が無くてもいいんじゃないか」と思う方もいると思います。
今回はなくても特に影響はありませんが、こちらについてもできるだけ意識して付けることをおすすめします。
というのも、「先頭から」を指定しないと、行の途中からでも検索にマッチしてしまうことがあります。
意図的にそうする場合も持ちろんありますが、意図しない場合に、意図しない箇所を置換してしまう事故も想定されます。
なので、特に途中から検索する都合などがない場合は、特に慣れないうちは【^】を付けておくことをおすすめします。
4.まとめ
今回は私が何度もお世話になった「正規表現」について書いてきました。
今回紹介した表現はかなり初歩的な内容であり、これだけでは表現できないものもたくさんあります。
しかし、この記事を読んだ後ならば「こんな表現をしたい」と思った際にご自身で調べて書ける程度にはなっていると思います。
正規表現が使えるだけで業務にかかる時間を短縮できるシーンは多々あると思いますので、是非これからも活用していただければと幸いです。
それでは、良き正規表現ライフを。
また次の記事でお会いしましょう。