2020年12月7日

パターンとフラグ

正規表現は、テキスト内を検索および置換するための強力な方法を提供するパターンです。

JavaScriptでは、RegExpオブジェクトを介して利用できるほか、文字列のメソッドにも統合されています。

正規表現

正規表現(「regexp」または単に「reg」とも呼ばれます)は、パターンとオプションのフラグで構成されています。

正規表現オブジェクトを作成するには、2つの構文を使用できます。

「長い」構文

regexp = new RegExp("pattern", "flags");

そしてスラッシュ"/"を使用した「短い」構文

regexp = /pattern/; // no flags
regexp = /pattern/gmi; // with flags g,m and i (to be covered soon)

スラッシュ/.../は、正規表現を作成していることをJavaScriptに伝えます。文字列の引用符と同じ役割を果たします。

どちらの場合も、regexpは組み込みのRegExpクラスのインスタンスになります。

これらの2つの構文の主な違いは、スラッシュ/.../を使用したパターンでは、式を挿入できません(${...}を使用した文字列テンプレートリテラルなど)。完全に静的です。

コード記述時に正規表現がわかっている場合はスラッシュを使用します。これは最も一般的な状況です。一方、動的に生成された文字列から正規表現を「その場で」作成する必要がある場合は、new RegExpがよく使用されます。例えば

let tag = prompt("What tag do you want to find?", "h2");

let regexp = new RegExp(`<${tag}>`); // same as /<h2>/ if answered "h2" in the prompt above

フラグ

正規表現には、検索に影響を与えるフラグを付けることができます。

JavaScriptには6つしかありません。

i
このフラグを使用すると、検索は大文字と小文字を区別しません。Aaの違いはありません(以下の例を参照)。
g
このフラグを使用すると、検索はすべてのマッチを検索します。このフラグがない場合は、最初のマッチのみが返されます。
m
複数行モード(アンカー ^ $ の複数行モード、フラグ "m"の章で説明します)。
s
「dotall」モードを有効にします。これにより、ドット.で改行文字\nにマッチできます(文字クラスの章で説明します)。
u
完全なUnicodeサポートを有効にします。このフラグにより、サロゲートペアの処理が正しくなります。Unicode:フラグ "u" とクラス \p{...}の章で詳しく説明します。
y
「スティッキー」モード:テキスト内の正確な位置で検索します(スティッキーフラグ "y"、位置での検索の章で説明します)。

ここから、配色は以下のようになります。

  • 正規表現 –
  • 文字列(検索する場所)–
  • 結果 –

検索:str.match

前述のように、正規表現は文字列メソッドと統合されています。

メソッドstr.match(regexp)は、文字列str内のregexpのすべてのマッチを見つけます。

3つの動作モードがあります。

  1. 正規表現にフラグgがある場合、すべてのマッチの配列を返します。

    let str = "We will, we will rock you";
    
    alert( str.match(/we/gi) ); // We,we (an array of 2 substrings that match)

    Weweの両方が見つかることに注意してください。フラグiにより、正規表現は大文字と小文字を区別しません。

  2. そのようなフラグがない場合、最初のマッチのみを配列形式で返します。完全なマッチはインデックス0にあり、その他の詳細はプロパティにあります。

    let str = "We will, we will rock you";
    
    let result = str.match(/we/i); // without flag g
    
    alert( result[0] );     // We (1st match)
    alert( result.length ); // 1
    
    // Details:
    alert( result.index );  // 0 (position of the match)
    alert( result.input );  // We will, we will rock you (source string)

    正規表現の一部が括弧で囲まれている場合、配列には0以外のインデックスが含まれる場合があります。キャプチャグループの章で説明します。

  3. 最後に、マッチがない場合は、nullが返されます(フラグgの有無は関係ありません)。

    これは非常に重要なニュアンスです。マッチがない場合、空の配列ではなくnullが返されます。これを忘れると、例えばエラーが発生する可能性があります。

    let matches = "JavaScript".match(/HTML/); // = null
    
    if (!matches.length) { // Error: Cannot read property 'length' of null
      alert("Error in the line above");
    }

    結果を常に配列にするには、このように記述できます。

    let matches = "JavaScript".match(/HTML/) || [];
    
    if (!matches.length) {
      alert("No matches"); // now it works
    }

置換:str.replace

メソッドstr.replace(regexp, replacement)は、文字列str内でregexpを使用して見つかったマッチをreplacementで置換します(フラグgがある場合はすべてのマッチ、そうでない場合は最初のマッチのみ)。

例えば

// no flag g
alert( "We will, we will".replace(/we/i, "I") ); // I will, we will

// with flag g
alert( "We will, we will".replace(/we/ig, "I") ); // I will, I will

2番目の引数はreplacement文字列です。特殊文字の組み合わせを使用して、マッチの断片を挿入できます。

記号 置換文字列での動作
$& マッチ全体を挿入します。
$` マッチの前にある文字列の一部を挿入します。
$' マッチの後に文字列の一部を挿入します。
$n nが1~2桁の数値の場合、n番目の括弧の内容を挿入します。キャプチャグループの章で詳しく説明します。
$<name> 指定されたnameの括弧の内容を挿入します。キャプチャグループの章で詳しく説明します。
$$ 文字$を挿入します。

$&の例

alert( "I love HTML".replace(/HTML/, "$& and JavaScript") ); // I love HTML and JavaScript

テスト:regexp.test

メソッドregexp.test(str)は、少なくとも1つのマッチを探し、見つかった場合はtrueを、そうでない場合はfalseを返します。

let str = "I love JavaScript";
let regexp = /LOVE/i;

alert( regexp.test(str) ); // true

この章の後半では、さらに正規表現を学習し、さらに多くの例を説明し、他のメソッドについても説明します。

メソッドに関する完全な情報は、RegExpとStringのメソッドの記事に記載されています。

まとめ

  • 正規表現は、パターンとオプションのフラグgimusyで構成されています。
  • フラグと特殊記号(後で学習します)がない場合、正規表現による検索は部分文字列検索と同じです。
  • メソッドstr.match(regexp)は、マッチを検索します。gフラグがある場合はすべて、そうでない場合は最初のマッチのみです。
  • メソッドstr.replace(regexp, replacement)は、regexpを使用して見つかったマッチをreplacementで置換します。gフラグがある場合はすべて、そうでない場合は最初のマッチのみです。
  • メソッドregexp.test(str)は、少なくとも1つのマッチがある場合はtrueを、そうでない場合はfalseを返します。
チュートリアルマップ

コメント

コメントする前にこれを読んでください…
  • 改善点の提案がある場合は、コメントする代わりにGitHub issueまたはプルリクエストを送信してください。
  • 記事の内容が理解できない場合は、詳しく説明してください。
  • 短いコードを挿入するには<code>タグを使用し、複数行の場合は<pre>タグで囲み、10行を超える場合はサンドボックス(plnkrjsbincodepen…)を使用してください。