正規表現のテスト<Javascript<木暮仁

スタートページJavascript正規表現の基礎

正規表現(regular expression)のテスト

参照:「正規表現の基礎」
正規表現に関しては、多くの解説書やWebサイトがあります。ここで取り上げたものは一部分にすぎず、しかも初歩的なものです。あえてこれを作成したのは、script作成時にうまく処理できなかったときのテスト用にしたかったからです。


単純な正規表現を用いた検索と置換

入力文
正規表現を「/bcd/gi」とするときは、検索文字列を「bcd」検索修飾子を「gi」にしてください。
検索文字列 検索修飾子
検索文字列 検索修飾子 置換文字列
検索文字列 検索修飾子
検索文字列 検索修飾子
search:最初の一致文字列位置
「結果 = 入力文.search(正規表現)」は、入力文中で正規表現に一致した最初の文字列の位置を戻します。
「最初の文字列の位置」ですので、検索修飾子の「g」は無視されます。配列にはなりません。
一致する文字列がない場合は、結果は-1(Nullではない)になります。
replace:一致文字列の置換
「出力文 = 入力文.replace(正規表現, 置換文字列)」は、入力文に正規表現に一致した文字列があれば、その文字列を置換文字列に置換した結果が出力文になります。
  • 一致する文字列がない場合は、「出力文 = 入力文」になります。
  • match:一致文字列があるかどうかの検索
    結果 = 入力文.match(正規表現)は、入力文中の正規表現に一致した文字列があるかを検索します。
    一致すれば、結果は一致した文字列になります。g指定があれば、すべての一致部分を配列として、一致した文字列が先頭から、結果[0], 結果[1], ・・・に入ります。その個数は、「結果.length」で得られます。
    一致する文字列がない場合は、結果はNullになります。
    「入力文に一致した文字列がある場合~」は、次のような記述になります。
       if (入力文.match(正規表現)) {
         :
       }
    leftContext :最後の一致文字列の左側文字列
    検索修飾子のgは必須です。
    記述形式はmatchやreplaceとは異なります。
      出力行 = 入力文.match(正規表現); (出力行は一時的な変数、「g」指定)
      左側文字列 = RegExp.leftContext;
      右側文字列 = RegExp.rightContext;
    とします。
    一致した文字列がない場合、左側文字列も右側文字列もNullになります。

    split(分割)

    入力文
      分割文字列

    「出力行 = 入力文.split(分割文字列);」とすると、入力文が分割文字列(例えば「,」)の前後で分割されて、出力行[0], 出力行[0], ・・・の配列になります。
    出力行の行数は「出力行.length」で得られます。分割文字列が存在しないと、行数は1になり、出力行[0] が入力行と同じになります。
    確かではないのですが、「,」の後にある(出力行の左端)の半角空白は削除され、「,」の後にある(出力行の左端)に複数の半角空白があっても1個になるようです。


    文字列の長さや位置など

    入力文=
    文字列の長さ:
    1文字の取出し:位置
    一致位置:検索文字
    部分文字列:左端 右端
    部分文字列:左端文字 右端文字

    length
    「文字列の長さ」は、入力文.lengthで求められます。
    半角文字も全角文字も1つとして数えます。全角文字は2バイトだから~というような配慮は無用です。
    charAt
    入力文.charAt(位置)により、指定した位置の文字をとりだします。
    ところが、文字の位置は先頭を0として数えます。文字列が「12345あいうえおabcde」ならば、「1」の位置は0、「あ」の位置は5、そして「e」の位置は14になります。最後の位置が「文字列の長さ-1」になることに注意。
    indexOf
    文字列で、特定の文字(文字列)がどの位置にあるかは、入力文.indexOf(検索文字)で得られます。検索文字を「あい」とすると、その先頭文字「あ」のある位置(0から数えるので5)が戻り値になります。
    不一致のときは、nullではなく-1になることに注意。
    入力文.indexOf(検索文字, 検索先頭位置)として、検索範囲を絞ることができます。「入力文.indexOf("a", 5);」とすると、5の位置(すなわち「あ」の位置)から検索します。このとき、戻り値は10(5ではない!)になります。
    なお、入力文の末尾から検索するときはlastindexObを使います。
    substring
    位置を指定した部分文字列は入力文.substring(左端, 右端)で得られます。左端位置を3(4番目の文字=4)右端位置を8(9番目の文字=え)とすると、左端を含み右端を含まない「45あいう」となります。両端を含ませたいときは、入力文.substring(左端, 右端+1)とします。
    subIndex(このような関数はありません)
    ここでは、両端の文字を含む部分文字列を取り出します。
            入力文.substring(                // A
          入力文.indexOf(左端文字),          // B
          入力文.indexOf(右端文字) + 右端文字.length) // C
    
    Aの入力文.substring(左端位置, 右端位置)の左端位置、右端位置をB・Cで与えています。
    両端の文字を含ませないならば、B・Cを次のように変えます。
            入力文.substring(                // A
          入力文.indexOf(左端文字) - 左端文字.length, // B
          入力文.indexOf(右端文字))          // C
    
    この場合でも、入力文を左から探索して最初に見つかった左端文字・右端文字の位置が対象になります。そのため、右端文字が左端文字より左にあると面倒になります。

    空白の削除

    入力文
    検索文字列 検索修飾子
    「_」は半角空白、□は全角空白を示します
              半角空白のみ削除 全角空白も削除
    全体を対象        _       \s または [_□]
    行頭・行末だけを対象  ^_+|_+$       ^\s+|\s+$ 
    

    Help! 「\s」について

    文法では、文字クラス「\s」は「半角空白を指し、全角空白は含まない」としています。
    ところが、
      "__□_abcde□□__fghij__□_".replace(/\s/g, "x") → "xxxxabcdexxxxfghijxxxx"
      "__□_abcde□□__fghij__□_".replace(/_/g, "x")  → "xx□xabcde□□xxfghijxx□x"
    となります。
    すなわち、「\sは半角・全角どちらの空白も含む」ようです。
    私は、この理由がわかりません。ご教示いただければ幸甚です。hitoshi@kogures.com


    テキスト複数行と改行コード

       

    上の文章を、そのまま取り込んで「入力文」とします。

    (alert)
    入力文をalertで表示すると、フレームと同じ改行や空白行が表示されます。
    (getElementById)
    ところが、「document.getElementById("複数行表示場所").innerHTML = 入力文」としたとき、1行で表示されます。
    その理由は、テキストデータの改行コードは、Windowsでは「\r\n」その他OSでは「\n」ですが、HTMLでは、<br>などのタグが改行をコントロールします。ケース2では改行コードは残っているのに、「改行」の機能をもたないのです。

    (relpace)改行コードの削除
    入力文を正規表現などで加工するとき、改行コードを削除して1行にしたほうが取扱いが容易になるので、まず改行コードを削除するのが常套手段です。
      入力文 = 入力文.replace(/[\r\n]/g, "");
    [\r\n] とは、\r または \n の意味で、どちらのコードも "" になります。 ここでは、結果をalertで表示します。改行コードがなくなり1行になります。
    (split)各行の配列化
    改行コードを分離コードとして、入力行を各行の配列にします。
      「\r」の削除:   入力文 = 入力文.replace(/\r/g, "");
      「\n」による分離: 行 = 入力文.split("\n");

    ケース4+空行の削除
    ここでの空行とは、半角空白あるいは全角空白(□で表示)だけの行も含むものとします。
    (上の入力文の3行目に適宜半角・全角の空白を入れてテストしてください)
    半角空白の正規表現は「\s」ですが、全角空白も対象にするので、「[\s□]」を削除します。
      仮行 = 行.replace(/[\s□]/g, "");
    により、仮行が空白行ならば、仮行="" となるので、その行を読み飛ばせばよいのです。

    var 新行 = new Array();                // 空白行を除いた行を新設
    var j = 0;                             // 新行配列の添字
    入力文 = 入力文.replace(/\r/g, "");    // \r の削除
    行 = 入力文.split("\n");               // \nによる分離
    for (i=0; i<行.length; i++) {
        var 仮行 = 行[i].replace(/[\s□]/g, ""); // 空白の削除
        if (仮行 != "") {
             新行[j] = 行[i];
             j++;
        }
    }
    

    URLのパスとファイルの分離

      入力 URL: "aaa/bbb/xxx.html"    "xxx.html"
      出力 パス:   "aaa/bbb/"            ""
         ファイル:"xxx.html"            "xxx.html"
    
    URL= →パス= ファイル=
    var パス = "";
    var ファイル = URL;
    var 正規表現 = new RegExp("/","g");    // A
    if (URL.match(正規表現)) {          // B
        パス = RegExp.leftContext + "/";   // C
        ファイル = RegExp.rightContext;    // D
    }
    

    複雑な正規表現

    タグ(<~>の部分)の削除→replace(/<.*?>/g, "")

    入力文
    検索文字列 検索修飾子

    囲まれた範囲が複数ある場合の取出し→「A.*?B」

    ここでは( )で囲まれた内部だけを取り出します。

    入力文
    検索文字列 検索修飾子

    文字Aと文字Bで囲まれた部分文字列: 最長一致「A.*B」、最短一致「A.*?B」

    入力文
    最長一致検索文字列 = 最短一致検索文字列 =

    二つの正規表現で囲まれた内部の置換

    入力文
    検索文字列(前) 検索文字列(後) 置換文字列

    グループ化「( )」による取出し→(検索1)文字列(検索2)

    検索1と検索2の間に文字列がある部分、ここでは「英小文字列 + あ + 数字列」を取り出します。
    検索1での文字列(「英小文字列」の部分)がRegExp.$1、検索2での文字列(「数字列」の部分)がRegExp.$2に得られます。

    入力文
    検索文字列 検索修飾子

    先読み→X(?=A) Aに先行するXの取出し

    ここでは、「円」の直前の数字列を取り出します。→\d+(?=円)

    入力文
    検索文字列 検索修飾子