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