preg_replace shim と eval サポート
これは非常にお勧めできません。しかし、あなたがプログラマーでない場合、またはひどいコードを本当に好む場合は、代替関数を使用して一時的にフラグpreg_replace
を機能させ続けることができます。/e
/**
* Can be used as a stopgap shim for preg_replace() calls with /e flag.
* Is likely to fail for more complex string munging expressions. And
* very obviously won't help with local-scope variable expressions.
*
* @license: CC-BY-*.*-comment-must-be-retained
* @security: Provides `eval` support for replacement patterns. Which
* poses troubles for user-supplied input when paired with overly
* generic placeholders. This variant is only slightly stricter than
* the C implementation, but still susceptible to varexpression, quote
* breakouts and mundane exploits from unquoted capture placeholders.
* @url: https://stackoverflow.com/q/15454220
*/
function preg_replace_eval($pattern, $replacement, $subject, $limit=-1) {
# strip /e flag
$pattern = preg_replace('/(\W[a-df-z]*)e([a-df-z]*)$/i', '$1$2', $pattern);
# warn about most blatant misuses at least
if (preg_match('/\(\.[+*]/', $pattern)) {
trigger_error("preg_replace_eval(): regex contains (.*) or (.+) placeholders, which easily causes security issues for unconstrained/user input in the replacement expression. Transform your code to use preg_replace_callback() with a sane replacement callback!");
}
# run preg_replace with eval-callback
return preg_replace_callback(
$pattern,
function ($matches) use ($replacement) {
# substitute $1/$2/… with literals from $matches[]
$repl = preg_replace_callback(
'/(?<!\\\\)(?:[$]|\\\\)(\d+)/',
function ($m) use ($matches) {
if (!isset($matches[$m[1]])) { trigger_error("No capture group for '$m[0]' eval placeholder"); }
return addcslashes($matches[$m[1]], '\"\'\`\$\\\0'); # additionally escapes '$' and backticks
},
$replacement
);
# run the replacement expression
return eval("return $repl;");
},
$subject,
$limit
);
}
本質的には、その関数をコードベースに含めて 、フラグが使用された場所を編集preg_replace
するだけです。preg_replace_eval
/e
長所と短所:
- Stack Overflow のいくつかのサンプルで実際にテストしたところです。
- 簡単なケースのみをサポートします (変数の検索ではなく、関数呼び出し)。
- さらにいくつかの制限事項と注意事項が含まれています。
- 式の失敗に対して、位置がずれて理解しにくいエラーが発生します。
- ただし、まだ使用可能な一時的な解決策であり、への適切な移行を複雑にすることはありません
preg_replace_callback
。
- そして、ライセンスのコメントは、人々がこれを過度に使用したり広めたりするのを思いとどまらせることを目的としています.
置換コードジェネレーター
これはやや冗長です。しかし、手動でコードをpreg_replace_callback
. これには実質的に時間がかかりますが、コード ジェネレーターが/e
置換文字列を式に展開する際の問題は少なくなります。これは非常に目立たない変換ですが、最も一般的な例ではおそらく十分です。
この関数を使用するには、壊れたpreg_replace
呼び出しを編集して1 回preg_replace_eval_replacement
実行します。これにより、その場所で使用される対応するブロックが出力されます。preg_replace_callback
/**
* Use once to generate a crude preg_replace_callback() substitution. Might often
* require additional changes in the `return …;` expression. You'll also have to
* refit the variable names for input/output obviously.
*
* >>> preg_replace_eval_replacement("/\w+/", 'strtopupper("$1")', $ignored);
*/
function preg_replace_eval_replacement($pattern, $replacement, $subjectvar="IGNORED") {
$pattern = preg_replace('/(\W[a-df-z]*)e([a-df-z]*)$/i', '$1$2', $pattern);
$replacement = preg_replace_callback('/[\'\"]?(?<!\\\\)(?:[$]|\\\\)(\d+)[\'\"]?/', function ($m) { return "\$m[{$m[1]}]"; }, $replacement);
$ve = "var_export";
$bt = debug_backtrace(0, 1)[0];
print "<pre><code>
#----------------------------------------------------
# replace preg_*() call in '$bt[file]' line $bt[line] with:
#----------------------------------------------------
\$OUTPUT_VAR = preg_replace_callback(
{$ve($pattern, TRUE)},
function (\$m) {
return {$replacement};
},
\$YOUR_INPUT_VARIABLE_GOES_HERE
)
#----------------------------------------------------
</code></pre>\n";
}
単なるコピー&ペーストはプログラミングではないことに注意してください。生成されたコードを実際の入力/出力変数名または使用コンテキストに戻す必要があります。
- 具体的には、前の呼び出しが で使用された
$OUTPUT =
場合、割り当てを行わなければなりません。preg_replace
if
- ただし、一時変数または複数行のコード ブロック構造を保持することをお勧めします。
また、置換式では、読みやすさの改善や手直しが必要になる場合があります。
- たとえば
stripslashes()
、リテラル式ではしばしば冗長になります。
- 変数スコープのルックアップには、コールバックの/内の
use
または参照が必要です。global
- 不均等に引用符で囲まれた
"-$1-$2"
キャプチャ参照は、 への単純な変換によって構文的に壊れてしまい"-$m[1]-$m[2]
ます。
コード出力は単なる開始点です。はい、これはオンラインツールとしてもっと便利だったでしょう. このコード書き換えアプローチ (編集、実行、編集、編集) はやや非現実的です。ただし、タスク中心のコーディング (より多くのステップ、より多くの発見) に慣れている人にとっては、より親しみやすいものになる可能性があります。したがって、この代替手段により、さらにいくつかの重複する質問が抑制される可能性があります。