WikiChree.COM 新規   編集   添付   管理  



トップ   編集 編集〔GUI〕 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS   ログイン

Pkript/文法/正規表現/old の変更点

#author("2026-08-31T22:16:03+09:00","default:guide","guide")
* Pkript/文法/正規表現 [#t8cff4c1]

/パターン/フラグ と書きます。値としての型は RegExp で、変数にも入れられます。

 const DATE = /(\d{4})-(\d{2})-(\d{2})/;

 function plugin_hello_convert(e) {
     const line = e.args[0];
     if (!DATE.test(line)) return "<p>日付ではありません</p>";
     return "<p>" + htmlsc(line.replace(DATE, "$1年$2月$3日")) + "</p>";
 }

#contents

** 有効・無効の切り替え [#gc2c823f]

既定で有効です。plugin/pkript.inc.php の PKRIPT_REGEX を 0 にすると無効になり、/ は除算としてだけ働きます。

** フラグ [#rfead1ac]

|~フラグ|~意味|h
|g|1件目で止めず全件を対象にする|
|i|大文字小文字を区別しない|
|m|^ と $ が行頭・行末にも一致する|
|s|. が改行にも一致する|

UTF-8としての解釈は''常に有効''です(PCREの u 修飾子が必ず付きます)。これが無いと . が1文字の途中に一致してしまうため、切り替えられません。

JavaScript の y(sticky)は、対応する lastIndex を持たないため用意していません。

** メソッド [#d28f9e52]

|~呼び出し|~戻り値|h
|re.test(str)|一致すれば true|
|re.exec(str)|最初の一致の配列(全体, グループ1, ...)。無ければ null|
|re.source() / re.flags() / re.global()|書いたパターン / フラグ / g の有無|
|str.match(re)|g 無し: 最初の一致の配列。g 有り: 一致した文字列すべて。無ければ null|
|str.matchAll(re)|一致ごとの配列の配列。無ければ空配列|
|str.search(re)|最初の一致の位置(''文字数'')。無ければ -1|
|str.replace(re, to)|g 有りなら全件、無ければ1件を置換|
|str.replaceAll(re, to)|g の有無によらず全件を置換|
|str.split(re)|一致で分割した配列|

match が g の有無で形を変えるのは JavaScript と同じ挙動に合わせたものです。グループが要る場合は matchAll か exec を使ってください。

 const m = "2024-05-06".match(/(\d+)-(\d+)/);
 // m は ["2024-05", "2024", "05"]

 const all = "a1 b2".matchAll(/([a-z])(\d)/g);
 // all は [["a1","a","1"], ["b2","b","2"]]

*** 置換文字列 [#cacb5aa1]

|~書き方|~意味|h
|$1 〜 $99|グループ|
|${1}|番号の切れ目を明示したグループ。"${1}0" のように直後に数字を置ける|
|$&|一致した全体|
|$$|$ そのもの|

** 使えない書き方 [#ye1cc55e]

|~書き方|~理由|h
|(?R) (?0) (?1) (?&name)|再帰・サブルーチン呼び出し。照合ではなく実行になります|
|(?C...)|コールアウト|
|\K \C|一致開始位置やバイト単位の操作。位置の報告が嘘になります|

グループとして書けるのは (...) (?:...) (?=...) (?!...) (?<=...) (?<!...) (?<名前>...) とインラインフラグ (?i) だけです。''ホワイトリスト''なので、PCREが今後増やす構文も既定では通りません。

** 暴走の止め方 [#j63d0f22]

正規表現は、スクリプトが「そこに辿り着くまでのステップ数」とまったく無関係な時間を使える唯一の場所です。/(a+)+$/ のようなパターンは1回の照合の中で何分でも走り得ますし、その間はステップ数も実行時間も数える機会がありません。

そのため''すべての照合をPCREのバックトラック上限の下で走らせます''(PKRIPT_REGEX_BACKTRACK、既定100,000。PHPの既定値は1,000,000です)。

上限に達した照合は「一致しなかった」ではなく''リソース上限エラー''になります。false を返すとスクリプトに「一致しなかった」と嘘をついたことになり、ページの内容が黙って変わってしまうためです。したがって try / catch でも捕まえられません。

パターンの検査は''解析時''に行います。書き方の誤りや使えない構文は実行前にエラーになり、ASTキャッシュには検査を通ったパターンしか載りません。パターンの長さは PKRIPT_MAX_REGEX(既定512バイト)までです。

** / の解釈 [#q4fcb2a5]

JSXの < と同じ規則です。''式が始まれる位置''の / だけが正規表現になります。

 let a = 10 / 2;          // 除算
 return /a+/.test(s);     // 正規表現(return の直後)
 const r = /a+/;          // 正規表現(= の直後)
 return f(10) / 2;        // 除算() の直後)

識別子・数値・)・] の直後の / は除算のままなので、既存のスクリプトの意味は変わりません。// と /* はどの位置でもコメントとして先に処理されます。