プログラミングで文字列を扱う際に便利な機能の1つに、正規表現(Regular Expression)というものがあります。
文字列の検索メソッドや操作メソッドで、条件に一致する文字列を指定する際に正規表現を使用すると、より複雑で柔軟な条件に対応できるようになります。
そこで、今回の記事では、JavaScriptで正規表現を使用する方法についての解説を行っていきたいと思います。
正規表現の実践例も合わせて紹介するので、参考にしてみてください。
JavaScriptの正規表現(RegExp)とは?
正規表現とは、メタ文字と呼ばれる特別な文字の組み合わせによって、文字列をパターン表現する記法のことを言います。
正規表現を使用することにより、「3桁の数字」 や 「連続する2文字以上の英字」 といったような、文字列の並びに対する特定の条件を指定することができます。
例えば、入力フォームでユーザーに情報を入力してもらう際に、正しい形式で入力されているかをチェックするケースなど、決まった内容の文言ではなく特定のパターンに一致するか否かで判断したい場合などに活用されます。
また、JavaScriptにおける正規表現は、RegExpオブジェクトというデータ型で扱われます。
正規表現の使い方
それでは早速、JavaScriptで正規表現を使用する方法について解説していきたいと思います。
基本構文
JavaScriptで正規表現を使用する際の記述方法は、以下の2種類があります。
① RegExpオブジェクトのコンストラクターを経由する方法
【基本構文】
const regex = new RegExp("正規表現", "オプション");②正規表現リテラルを使用する方法
【基本構文】
const regex = /正規表現/オプション;コンストラクターとリテラルではコンパイルのタイミングが異なり、コンストラクターは実行時に、リテラルは JavaScript がロードされる際のコンパイル時に同時にコンパイルされます。
上記の理由から、リテラルを使用した正規表現は値を動的に変更することが不可能となっており、既に決まっているパターンの正規表現にしか対応することができません。
そのため、パターンが動的に変化したり、ユーザーの入力値などからパターンを取得する場合には、コンストラクターを使用する必要があります。
一方で、パフォーマンスの面ではリテラルの方に軍配が上がるため、決まったパターンに対してはリテラルを使用するのがおすすめです。
正規表現パターンを種類別で覚える
メタ文字を使用して記述する正規表現パターンは、大まかに分けて以下の4つの種類があります。
- 一致条件とする文字のリスト、もしくは範囲を表現するパターン(文字クラス)
- 文字の繰り返し回数を表現するパターン(量指定子)
- 文字位置を表現するパターン(アンカー)
- 既存で定義されている文字の条件リストを表現するパターン(文字クラスエスケープ)
それぞれのパターンについて、順に確認していきましょう。
文字リストや文字範囲を表すパターン
1つ目は、文字クラスを使用して表現する正規表現パターンです。
[ ] の中に記述した文字のリスト、もしくは文字の範囲をパターンとして指定します。
例えば、以下のように 「 [abc] 」と記述した場合、a か b か c のいずれかに該当する1文字を対象とします。
【サンプルコード】
// a, b, c のいずれか1文字
const reg = /[abc]/;また、[^…] といった形式で [ ] の中に ^ を付けて記述すると、反対に指定した範囲以外の文字が対象となります。
【サンプルコード】
// 小文字の a~z のいずれか1文字
const regex = /[^abc]/;単一ごとの文字の指定でなく、一定範囲をまとめて指定したい場合は、開始値と終了値を – で区切って記述します。
【サンプルコード】
// 小文字の a~z のいずれか1文字
const reg = /[a-z]/;
// 0~9 のいずれか1文字
const reg = /[0-9]/;文字の繰り返しを表すパターン
特定の文字の繰り返しを表現したい場合は、量指定子を使用します。
正規表現で使用可能な量指定子は、以下の通りです。
【 * 】 … 直前のパターンの 0 回以上の繰り返し
【 + 】 … 直前のパターンの 1 回以上の繰り返し
【 ? 】 … 直前のパターンの 0 回か 1 回の繰り返し
【 {n} 】 … 直前のパターンの n 回の繰り返し
【 {n,} 】 … 直前のパターンの n 回以上の繰り返し
【 {n,m} 】 … 直前のパターンの n ~ m 回の繰り返し
以下の例のように、使用する量指定子によって一致するパターンが変化する場合があります。
【サンプルコード】
const str = "1 10 100";
const regex1 = /10*/g;
// 1, 10, 100
const regex2 = /10+/g;
// 10, 100
const regex3 = /10?/g;
// 1, 10, 10
const regex4 = /10{2}/g;
// 100
const regex5 = /10{1,}/g;
// 10, 100
const regex6 = /10{0,2}/g;
// 1, 10, 100文字列の先頭・末尾を表すパターン
文字列の先頭、もしくは末尾を表したい場合は、アンカーと呼ばれるメタ文字を使用します。
【 ^ 】 … 文字列の先頭
【 $ 】 … 文字列の末尾
文字列の先頭を表したい場合は、正規表現パターンの冒頭に ^ を記述します。
【サンプルコード】
const regex = /^apple/;
// 先頭に appleがあるので対象となる
const str1 = "apple,banana";
// appleが先頭にないので対象外
const str2 = "banana,apple";反対に、文字列の末尾を表したい場合は、正規表現パターンの末尾に $ を記述します。
【サンプルコード】
const reg = /apple$/;
// appleが末尾にないので対象外
const str1 = "apple,banana";
// 末尾に appleがあるので対象となる
const str2 = "banana,apple";特殊な意味を表す文字パターン
メタ文字の中には、文字クラスエスケープという、言語仕様で定義された特別なパターンを表すメタ文字が存在します。
使用可能な文字クラスエスケープは、以下の通りです。
【 . 】 … 改行文字を除く1文字
【 \w 】 … 大文字/小文字の英字、数字、アンダースコアに該当 ([A-Za-z0-9_]と同義)
【 \d 】 … 数字1文字に該当 ([0-9] と同義)
【 \n 】 … 改行文字に該当
【 \r 】 … 復帰コード (行末から行頭に戻すコード) に該当直
【 \t 】 … タブ文字に該当
【 \s 】 … 空白文字に該当
\w, \d, \s は大文字でも指定可能が可能で、その場合は上記の条件以外の1文字を表します。
これらの既存パターンに一致する文字を対象とする場合は、文字クラス( [] )を使用するよりも簡潔にコードを記述することができます。
【サンプルコード】
const str = "apple 100 bnana 250";
const reg1 = /\d+/g;
// 100, 250
const reg = /\S+/g;
// apple, 100, bnana, 250正規表現のエスケープ
正規表現の使用時に、指定する内容によってはエスケープ処理が必要な場合があります。
該当するケースと処理方法について、詳しく見ていきましょう。
エスケープ処理が必要なケース
JavaScriptの正規表現でエスケープが必要となるケースは、主に以下の2パターンです。
- メタ文字として使用されている記号を文字として扱いたい場合
- RegExpコンストラクタでの指定時にバックスラッシュを使用する場合
文字クラスとして使用する [ ] や、量指定子として使用する + など、メタ文字として判断される記号を通常の文字として扱いたい場合は、メタ文字ではないことを示すためにエスケープする必要があります。
正規表現リテラルを使用する場合は、表記形式の一部として使用されるスラッシュもエスケープ対象となります。
また、引数に渡された正規表現を文字列として扱う RegExpコンストラクタの場合、正規表現リテラルと同じ構文でバックスラッシュを記述するとメタ文字として機能しないため、エスケープしてメタ文字として判断されるようにしなければなりません。
バックスラッシュによるエスケープ
エスケープ処理を行う際は、対象の文字の前にバックスラッシュを付けて記述します。
例えば、RegExpコンストラクタで文字クラスエスケープを扱う場合、以下のように記述してエスケープします。
【サンプルコード】
const regex = RegExp('\\d+');文字クラスエスケープにはバックスラッシュが含まれるため、メタ文字の前にバックスラッシュをもう1つ記述します。
その他のメタ文字についても、文字として扱いたい場合は対象の文字の直前にバックスラッシュを付けて記述します。
【サンプルコード】
// エスケープしたい文字の直前にバックスラッシュ
const regex1 = /\+10*/g;
// コンストラクタの場合はエスケープ時も2つ記述する
const regex2 = RegExp("\\+10*", "g");正規表現に関連するメソッド
正規表現は、様々なメソッドと組み合わせて活用することができます。
今回は、その中から代表的なものをいくつか紹介したいと思います。
matchメソッドで文字列の一致検索を行う
よく使用されるメソッドの1つが、matchメソッドです。
このメソッドでは、対象の文字列の中に指定の文字が含まれているか否かを検索することができます。
【基本構文】
対象文字列.match(検索内容);引数に正規表現を指定するため、特定のパターンに一致する文字列を検索したい場合によく活用されています。
検索内容が対象の文字列に含まれている場合は、一致する文字列を要素に持つ配列を戻り値として返します。
含まれない場合には null を返すため、if文の条件式として活用することもできます。
【サンプルコード】
const str = "This is apple";
const result = str.match(/apple$/);
if(result){
console.log('検索内容が含まれています');
}else{
console.log('検索内容が見つかりませんでした');
}【実行結果】
検索内容が含まれています使用時の注意点として、オプションを付けずに正規表現を指定すると、パターンに当てはまる文字列が複数存在する場合でも、最初に一致した文字列のみが結果として返されます。
当てはまる全ての文字列を取得したい場合は、正規表現の記述時にグローバルフラグ (g) を付けるようにしましょう。
【サンプルコード】
const str = "apple100 banana200";
// 最初に一致した文字列のみしか取得できない
const result1 = str.match(/[a-z]+/);
// グローバルフラグを付けると複数取得可能
const result2 = str.match(/[a-z]+/g);
// 取得した文字列が複数か否かで配列の中身も変わる
console.log(result1);
console.log(result2);【実行結果】
[ 'apple', index: 0, input: 'apple100 banana200', groups: undefined ]
[ 'apple', 'banana' ]searchメソッドで一致する文字列の位置を検索する
検索内容が対象の文字列に含まれている場合に、文字列の位置を取得したい時に使用するのが、searchメソッドです。
【基本構文】
対象文字列.search(検索内容);searchメソッドは、最初に検索内容と一致した文字列のうち、先頭に位置する文字のインデックスを返します。
検索内容が文字列に含まれない場合は、-1 を戻り値として返します。
【サンプルコード】
const str = "This is apple";
console.log(str.search(/apple/));
// 存在しない場合は -1 を返す
console.log(str.search(/banana/));【実行結果】
8
-1testメソッドで正規表現パターンに合致しているか判定する
同じく、文字列の検索に使用できるメソッドの1つに、testメソッドが存在します。
matchメソッドと searchメソッドの2つは、文字列型の既存メソッドとして用意されているものですが、testメソッドは RegExpオブジェクトで用意されているメソッドとなります。
そのため、正規表現(RegExpオブジェクト)に対してメソッドを使用し、引数に検索対象とする文字列を指定します。
【基本構文】
正規表現.test(対象文字列);メソッドの戻り値は、真偽値を返します。
細かい検索内容は必要なく、パターンに一致する文字列が含まれるか否かのみを知りたい場合に活用できます。
【サンプルコード】
const reg = /apple/;
console.log(reg.test("This is apple"));
console.log(reg.test("This is banana"));【実行結果】
true
false正規表現で文字列を操作する
ここまでは、文字列を検索するためのメソッドを中心に紹介してきましたが、その他にも正規表現を使用できるメソッドがいくつか存在します。
続いては、文字列の操作に活用できるメソッドを紹介していきます。
replaceメソッドで文字列を置換する
1つ目は、文字列の置換を行いたい時に活用可能な replaceメソッドについてです。
replaceメソッドは、対象の文字列内にある特定の文字を、別の文字に置換することができるメソッドです。
文字列から空白文字を除きたい、或いは日付表記を任意の書式に変更したいなど、文字列の一部のみを変更したい場合によく使用されます。
【基本構文】
対象の文字列.replace( 置換する文字, 置換後の文字 );メソッドの引数に正規表現を使用することにより、置換する文字の条件を柔軟に指定することができます。
【サンプルコード】
const str = "彼の名前は 山田 太郎 です。";
const result = str.replace(/\s+/g, "");
console.log(result);【実行結果】
彼の名前は山田太郎です。matchメソッドの時と同様に、グローバルフラグを付けずに正規表現を使用すると、最初に一致した文字しか置換が行われません。
該当する全ての文字列を置換したい場合は、グローバルフラグ (g) を必ず付けるようにしましょう。
splitメソッドで正規表現パターンによって文字列を分割する
2つ目は、文字列を分割したい場合に有効な splitメソッドについてです。
splitメソッドは、引数に指定した任意の区切り文字を基準として、対象の文字列を複数の要素に分割することができます。
分割されたそれぞれの文字列は、戻り値である配列に要素として格納されているため、別々の値として活用可能です。(ただし、区切り文字は結果に含まれません)
【基本構文】
str.split(区切り文字, 最大要素数);【サンプルコード】
const str = "apple123banana456peach";
const result = str.split(/\d+/);
console.log(result);【実行結果】
[ 'apple', 'banana', 'peach' ]正規表現の実践例
最後に、正規表現を使用してできる実践例をいくつか紹介します。
今回は、入力フォームの項目にもよくある電話番号と郵便番号を、正しい形式で入力されているかチェックする方法について解説したいと思います。
はじめに、電話番号の例から見ていきましょう。
ハイフンを入れる場合とそうでない場合の2通りがあるので、それぞれの指定方法について解説します。
まず、電話番号は必ず0から開始されるため、どちらのケースでもはじめに0を記述しましょう。
入力フォームなどの場合は0が文字列の先頭となるため、必要に応じて ^ を0の前に付けてください。
ハイフンを入れない場合は、0に続いて9桁、もしくは10桁の数字が連続して続くパターンを指定します。
先頭の位置指定と同様に、他の文字が後ろに続く可能性がない場合には、文末を示す $ を付けるとより安全です。
【サンプルコード】
const reg = /^0\d{9,10}$/;
const telNumber1 = "0311112222"; // 固定電話
const telNumber2 = "0120333444"; // フリーダイヤル
const telNumber3 = "09055556666"; // 携帯
const telNumber4 = "11122223333"; // エラーケース
console.log(reg.test(telNumber1));
console.log(reg.test(telNumber2));
console.log(reg.test(telNumber3));
console.log(reg.test(telNumber4));【実行結果】
true
true
true
falseハイフンを入れる場合は、区間ごとの桁数をそれぞれ指定します。
【サンプルコード】
const reg = /^0\d{1,3}-\d{2,4}-\d{3,4}$/;
const telNumber1 = "03-1111-2222"; // 固定電話
const telNumber2 = "0120-333-444"; // フリーダイヤル
const telNumber3 = "090-5555-6666"; // 携帯
const telNumber4 = "047--2223333"; // エラーケース
console.log(reg.test(telNumber1));
console.log(reg.test(telNumber2));
console.log(reg.test(telNumber3));
console.log(reg.test(telNumber4));【実行結果】
true
true
true
false続いて、郵便番号のケースを見ていきましょう。
郵便番号は、3桁の数字と4桁の数字を組み合わせて表現されます。
ハイフンなしの場合は7桁、ハイフンありの場合は3桁・ハイフン・4桁の順でパターンを指定しましょう。
【サンプルコード】
// ハイフンなしの場合
const reg1 = /^\d{7}$/;
console.log(reg1.test("1112222")); // 正常ケース
console.log(reg1.test("334444")); // エラーケース
// ハイフンありの場合
const reg2 = /^[0-9]{3}-[0-9]{4}$/;
console.log(reg2.test("111-2222")); // 正常ケース
console.log(reg2.test("3334-444")); // エラーケース【実行結果】
true
false
true
falseまとめ
いかがでしたか?今回は、JavaScriptで正規表現を使用する方法について解説しました。
正規表現を使用したパターンの指定方法は自由度が比較的高いため、慣れない内はどのように指定すればいいのか迷ってしまうこともあるかもしれません。
その場合は、実際に正規表現を使っていろんな文字列を検索してみるなどして、ある程度のパターンを掴んでいきましょう。
JavaScriptの勉強方法は?
書籍やインターネットで学習する方法があります。昨今では、YouTubeなどの動画サイトやエンジニアのコミュニティサイトなども充実していて多くの情報が手に入ります。
そして、より効率的に知識・スキルを習得するには、知識をつけながら実際に手を動かしてみるなど、インプットとアウトプットを繰り返していくことが重要です。特に独学の場合は、有識者に質問ができたりフィードバックをもらえるような環境があると、理解度が深まるでしょう。
ただ、JavaScriptに限らず、ITスキルを身につける際、どうしても課題にぶつかってしまうことはありますよね。特に独学だと、わからない部分をプロに質問できる機会を確保しにくく、モチベーションが続きにくいという側面があります。独学でモチベーションを維持する自信がない人にはプログラミングスクールという手もあります。費用は掛かりますが、その分スキルを身につけやすいです。しっかりと知識・スキルを習得して実践に活かしたいという人はプログラミングスクールがおすすめです。
プログラミングスクールならテックマニアがおすすめ!
ITスキル需要の高まりとともにプログラミングスクールも増えました。しかし、どのスクールに通うべきか迷ってしまう人もいるでしょう。そんな方にはテックマニアをおすすめします!これまで多くのITエンジニアを育成・輩出してきたテックマニアでもプログラミングスクールを開講しています。
<テックマニアの特徴>
・たしかな育成実績と親身な教育 ~セカンドキャリアを全力支援~
・講師が現役エンジニア ~“本当”の開発ノウハウを直に学べる~
・専属講師が学習を徹底サポート ~「わからない」を徹底解決~
・実務ベースでスキルを習得 ~実践的な凝縮カリキュラム~
このような特徴を持つテックマニアはITエンジニアのスタートラインとして最適です。
話を聞きたい・詳しく知りたいという方はこちらからお気軽にお問い合わせください。