〽️ 恐怖!無限ループ。
こんにちは。「ふ」です。
以前、replaceメソッドを使っての「" "で囲まれた部分のCSSを書き換える」方法を紹介しましたが、今回はその補足説明をさせていただきます。
execとは、execution(実行)、もしくはexecute(実行する)の意味だと思われます。文字列strと正規表現パターンregExpを用意します。
この文字列においてマッチした値を取り出したいときに
と記述します。
実行後、マッチした文字列が配列方式で返されます。
このとき、正規表現パターンを宣言した「var regExp」は、lastIndexというプロパティを持っています。最初に宣言した正規表現パターンに
と、グローバルオプションがつけられた場合、「1つ目のマッチは取り出しました、次は〇〇文字目から検索を始めます」の「〇〇」がInt(整数値)で返ってきます。
記述例を示します。exec()の結果は変数resultに代入しましょう。
resultを出力してみます。
マッチした文字列が配列に収められて返ってきました。
regExpのlastIndexはどうなっているでしょうか。
lastIndexは0から始まるので、「3」は画像のこの部分ですね。strでは「りんご」が2回登場しますが、このことから1回目のexecで取り出されたのは1つ目の「りんご」だったことが分かります。
あと2回やってみます。
2つ目の「りんご」が取り出され、lastIndexも更新されました。
str内には「りんご」は2つまでしかないので3回目はnullが返ってきます。
lastIndexもリセットされて0になりました。
次にグループ化について紹介します。正規表現パターンの一部を()で囲んでexec()メソッドを実行すると、返される配列の中に()で囲まれた部分が要素として加えられます。
exec()メソッドを実行します。
配列の1つ目はマッチした文字列全体、2つ目にグループ化された部分だけが入りました。
例えば「」に囲まれた部分をマッチさせて、その中身だけを取り出したい場合などには便利な機能ですね。
「」の中身だけが取り出せました。
扨(さて)このexec()メソッド、実際はwhile文を使ってマッチした文字列を順に取り出す、という使い方が多いかと思われます。
しかしこのとき起こりうるのが恐怖の無限ループ。その例を紹介しておきます。
上記のようにグローバルオプション「g」がついていないパターンでexec()メソッドを実行すると、そのlastIndexは更新されることがなく、毎回0にリセットされてしまいます。
ちょっとやってみますか。
lastIndexを出力する関数「tamesi」を何度か実行してみます。
regExpのlastIndexがご覧の通り、何度やっても0にリセットされてしまいます。通常regExpは「g」オプションがついているのでexec()が実行されるたびにlastIndexが更新され、検索がstrの最後まで進むと、while文の条件、
これを抜け出すことができ、メソッドが終了します。
ところが「g」オプションがついていない場合。lastIndexが毎回リセットされるため、常にexec()はテキストの先頭から検索を開始することになります。そのためwhile文の条件を抜け出すことができません。即ち、
を引き起こすのじゃ。エラーとなってしまいブラウザはロードできません。
もう1つはこれ。
while文の内部で正規表現パターンを宣言してしまっています。この場合も、lastIndexがその都度「0」となってしまうため、
これもあきまへん。
〜while文でexec()メソッドを使う際には注意しましょう。
ここまでexec()メソッドについて紹介させてもらいました。while文による無限ループは恐ろしいものです。
ところが現在「ふ」はまた別の無限ループ問題を抱えてしまっています。それがregExpのパターンに問題があるのか、while{ }内部での問題なのかまだ解明できていません。解明でき次第、また発信したいと思っています。閲覧ありがとうございました。
swift、web、ガジェットなど。役立つ情報や観ていてたのしいページを書いていきたいと思います。
🐧 twitter 🐧