今回は、
・正規表現とは?
・どんなときに使えるの?
・どうやって使うの?
・とりあえず使えるようになりたい
こんな方を対象に記事を書いていきます。
正規表現って記号だらけで難しそう
昔は「正規表現」と検索した結果を見るだけでゲロ吐きそうでした。
正直今でも苦手意識はあります。
しかし、正規表現は開発現場では嫌でも出てきますし、業務でも活用できるところが多いです。
今回はそんな正規表現に苦手意識のある僕が、
- わかりやすく
- 今日から使えるように
- 本当に必要なところをコンパクトに
紹介します。
この記事を見終わった頃には正規表現で簡単な検索はできるようになっているはずです。
正規表現とは
正規表現とは文字列のパターンを表現する方法です。
英語ではRegular Expressionなんて呼ばれます。
(なので変数宣言する際は「reg」や「re」なんて省略されたりすることが多いです)
正規表現を活用するとパターン一致を検出したり、検出箇所を置換したりできます。
いろんなプログラミング言語でもこの正規表現が扱えるようになっています。
どんなところで使われているの?
身近で正規表現が使用されている場所といえば、「フォーム」だと思います。
お問い合わせ・ネットで申し込み画面に電話番号やメールアドレスを入力途中に、
別の入力欄をタップしてしまったことないでしょうか。
赤文字で
「電話番号が正しくありません」
「メールアドレスが正しくありません」
と表示されたことはありませんか?
正規表現はユーザーがフォームに入力した内容が
Emailの形式(〇〇@△△.□□)になっているか
携帯電話番号の形式(0から始って2桁目が789のどれかで11桁の数字)になっているか
チェックするのに使われていたりします。
実際の業務ですと、
- エラー調査
- 影響調査
- データの前処理・分析
- バリデーション関数の作成
などで使った経験があります。
どうやってつかうの?
今回はプログラムでの実装を前提にJavascriptの記述例で紹介していきますが、
正規表現部分に関しては他言語でも大きく変化はありません。
関数の呼び出し部分を変更するなど、使用する言語に応じて適宜変更をお願いします。
まずは3つの最も重要かつ基本となる要素から紹介します。
①正規表現パターンの作り方
正規表現の作り方は2パターンあります。
const re = /sample/
const re = new RegExp('sample');
今回は「/」で囲む記述方式で説明していきます。
※上記2パターンはコンパイルのタイミングが異なります。
現在sampleとなっている部分を動的に処理したい場合はオブジェクトを使用してください。
それ以外の場合は処理速度やエスケープ文字を考慮しなくてよい点で、
圧倒的に「/」で囲むパターンが使いやすいです。
②文字列の一致判定
文字列の一致があるかないかを返してくれる関数はtest()になります。
使い方はこんな感じです。
正規表現(リテラルあるいはオブジェクト).test('検索対象となる文字列')
早速使ってみます。
const re = /sample/;
const str1 = "this is Sample";
const str2 = "this is sample";
console.log(`str1の結果は:${re.test(str1)}`);
console.log(`str2の結果は:${re.test(str2)}`);
str1とstr2の中からsampleという文字を探します。
str1は大文字のSample、str2は小文字のsample。
実行結果はこうなります。
str1の結果は:false
str2の結果は:true
大文字小文字を区別して一致している文字列が含まれるかを判定します。
③文字列に一致したものを返す
文字列に一致したものを返してくれる関数はmatchになります。
使い方はこんな感じです。
検索対象となる文字列.match(正規表現)
早速使ってみます。
const re = /3456789/
const str = "153486533456789879543215";
console.log(str.match(re));
strから3456789という部分があるかを確認できます。
実行結果はこうなります。
[
'3456789',
index: 8,
input: '153486533456789879543215',
groups: undefined
]
高度な検索をするために
test()、match()を紹介しました。
正規表現が持つメソッドには他にも、
「exec()」「matchAll()」「search()」「replace()」「replaceAll()」「split()」
がありますが、圧倒的に使用頻度が高いのはtest()とmatch()です。
しかし、これまで紹介してきた内容だと、通常の検索と大差はありません。
これから高度な検索をするための正規表現パターンを作るオプションフラグと特殊文字を紹介します。
オプションフラグ
正規表現にはオプションをつける事ができます。
オプションの付け方
const re = /sample/<span class="red">オプション</span><span class="red">フラグ</span>
オプションフラグにはd・i・s・y・g・u・mというオプションフラグが用意されています。
僕は(ディズニーガム)「disy gum」として語呂合わせで覚えてます。
実際の使い方はこんな感じです。
const re1 = /sample/g
const re2 = /sample/gi
const re3 = /sample/sig
よく使う3つのオプションをつけてみました。
オプションをつける順番は関係ありません。どの順番でもOKです。
オプション | 意味 |
---|---|
g | グローバル検索(globalのg) |
i | 大文字小文字無視(ignoreのi) |
m | 複数行検索(multilineのm) |
分かりづらい「g」と「m」の説明をしていきます。
グローバルオプション
グローバル検索とは全体を見るかどうかのオプションだと認識してください。
const normal_re = /pen/
const global_re = /pen/g
const str = 'pen pineapple apple pen';
let replaced1 = str.replace(normal_re, '');
let replaced2 = str.replace(global_re, '');
console.log(`オプションなし:${replaced1}`);
console.log(`オプションあり:${replaced2}`);
実行結果は
オプションなし: pineapple apple pen
オプションあり: pineapple apple
グローバルオプションをつけた方は全体からpenの文字がなくなりました。
マルチラインオプション
グローバルよりは説明からその機能を想定しやすいですが、やはり分かりづらいので例を挙げます。
以下の例の中の「^」は文字列の始まりがという意味です。
「^apple」であればappleで始まるという解釈になります。
「\n」は改行コードになります。
実際には
pen pineapple
apple pen
が一致判定の対象となっています。
const normal_re = /^apple/
const multiline_re = /^apple/m
const str = 'pen pineapple\napple pen';
let result1 = normal_re.test(str);
let result2 = multiline_re.test(str);
console.log(`オプションなし:${result1}`);
console.log(`オプションあり:${result2}`);
実行結果
オプションなし:false
オプションあり:true
特殊文字
続いて特殊文字です。
以下で紹介する特殊文字を覚えれば、
人が作った正規表現パターンの7割は読み取れるぐらいにはなるかと思います。
何から何までの”から”を表すハイフン「-」
[a-z]と書けばアルファベットの小文字のaから小文字のzまでとなる。
const re = /[a-z]/g;
const str = 'ABCdef012';
console.log(str.match(re));
実行結果
[ 'd', 'e', 'f' ]
全ての文字と数字を表す「\w」、その逆を表す「\W」
「\w」は全ての文字と数字を表します。[A-Za-z0-9_]と同じ意味を表します。
const re = /\w+/g;
const str1 = 'ABCdef012';
const str2 = 'ABC+def#012%&()0';
console.log(str1.match(re));
console.log(str2.match(re));
実行結果
[ 'ABCdef012' ]
[ 'ABC', 'def', '012', '0' ]
「\W」は全ての文字と数字以外を表します。
const re = /\W+/g;
const str1 = 'ABCdef012';
const str2 = 'ABC+def#012%&()0';
console.log(str1.match(re));
console.log(str2.match(re));
実行結果
null
[ '+', '#', '%&()' ]
全て数字を表す「\d」、その逆を表す「\D」
「\d」は全ての数字を表します。[0-9]と同じ意味を表します。
const re = /\d+/g;
const str1 = 'ABCdef012';
const str2 = 'ABC+def#012%&()0';
console.log(str1.match(re));
console.log(str2.match(re));
実行結果
[ '012' ]
[ '012', '0' ]
「\D」は数字ではないを表します。
const re = /\D+/g;
const str1 = 'ABCdef012';
const str2 = 'ABC+def#012%&()0';
console.log(str1.match(re));
console.log(str2.match(re));
実行結果
[ 'ABCdef' ]
[ 'ABC+def#', '%&()' ]
1回もしくは複数回連続を表すプラス「+」
const re = /[a-z]+/g;
const str = 'ABCdef012';
console.log(str.match(re)[0]);
実行結果
[ 'def' ]
0回もしくは複数回連続を表すプラス「*」
const re = /A[a-z]*/g;
const str = 'ABCAbcAzyx012';
console.log(str.match(re));
実行結果
[ 'A', 'Abc', 'Azyx' ]
決められた文字で終わるかを表す「$」
const re = /end$/;
const str1 = 'story~~then';
const str2 = 'story~~end';
console.log(re.test(str1));
console.log(re.test(str2));
実行結果
false
true
さいごに
今回エンジニア向けにプログラム上での実装を前提に紹介しましたが、
正規表現はsakuraエディターなどでも使用できます。
大量のCSVデータにパターン検索をかけたい時などはすごい役立つので、
正規表現の特殊文字を使えるようになった暁には、ぜひ活用できるところを探してみてください。
案外身近なところにあったりします。
コメント