0

文字列に対して preg_replace を使用したいのですが、文字列が一致しないのに、戻り文字列として空の文字列が返されます。

PHP Code:
    $sql = "k1 LIKE 'n' OR k2 LIKE 'n' OR k3 LIKE 'n' OR k4 LIKE 'n' OR k5 LIKE 'n' OR k6 LIKE '1' ";
    print "SQL: $sql<br>";
    $sql_A = preg_replace("/^([\w]+ LIKE\s?'?.*?'? OR )+ $/", "##$1##", $sql);
    print "=> $sql_A<br>";

戻り値:

SQL: k1 LIKE 'n' OR k2 LIKE 'n' OR k3 LIKE 'n' OR k4 LIKE 'n' OR k5 LIKE 'n' OR k6 LIKE '1'
=>

奇妙なことに、正規表現は一致しません。同じ結果を得ながら、できる限り文字列を単純化しようとしました。end-$ の直前に OR を追加することもできます。しかし、もう少しドロップするか、sthを追加するとすぐに。それ以外の場合は、通常の動作と適切な置換が得られます。

なぜこれが起こるのか誰にもわかりますか?多分私は見ていない間違いを犯したのかもしれません、多分これはバグですか?道に迷いました...

(LINUX サーバーで PHP バージョン 5.3.21 を使用)

--- 2013-04-24 21:30 ---

編集:

それが役立つ場合、私が最初に使用したデータは次のとおりです。

$sql = "SELECT count(*) AS anz FROM xxx_table LEFT JOIN yyy_table on yyy_table.devo=xxx_table.devo LEFT JOIN zzz_table ON (yyy_table.status=zzz_table.sid AND lang=1 AND yyy_table.for =zzz_table.for) LEFT JOIN kunde k on k.kd_nr = yyy_table.kd_nr LEFT JOIN locations l on l.lok_nr = yyy_table.lok_nr WHERE xxx_table.clear!='Y' AND xxx_table.ign!='Y' AND name NOT LIKE 'Container:%' AND name LIKE '%' AND event_prio LIKE '%' AND zzz_table.show='Y' AND ( k.ikd_nr LIKE '%n%' OR k.such LIKE '%n%' OR k.adr1 LIKE '%n%' OR k.adr2 LIKE '%n%' OR k.ort LIKE '%n%' OR k.strasse LIKE '%n%' )";
$sql_A = preg_replace("/(\((\s*[\w\.\-\`]+ (LIKE\s|=)\s*'?.+?'?\s*OR)* [\w\.\-\`]+ LIKE '%' (OR [\w\.\-\`]+ (LIKE\s|=)\s*'?.+?'?\s*)*\))/i", "", $sql);

また、結果は NULL でした (私が学んだように空の文字列ではありません;) (この preg_replace の目的は、SQL ステートメントの OR 条件を LIKE '%' パターンで識別して、これらの不要な OR 条件を削除することです。)

4

2 に答える 2

3

あなたの正規表現は、膨大な量のバックトラックを消費するように構築されています。

 echo preg_ last_ error()

収量2( PREG_BACKTRACK_LIMIT_ERROR)

もちろん、バックトラックを増やすこともできます:

 ini_set("pcre.backtrack_limit",100000000);

...これにより、この正規表現は機能しなくなりますが(一致しないため)、少なくとも元の文字列が返されます。より効率的な正規表現を作成することはより魅力的に思えますが、それを突き刺すには、目的の入力と出力が必要です。

編集:

もう少し見てみると、この正規表現は途中で少し役立つかもしれないと思います:

$sql_A = preg_replace(
   "/(\w+ LIKE\s*('(\\\.|[^'\\\]|)*'|[^\s]+))/",
   "##<$1>##",
   $sql);
于 2013-04-24T18:38:02.733 に答える
0

これを試して:

$sql = "k1 LIKE 'n' OR k2 LIKE 'n' OR k3 LIKE 'n' OR k4 LIKE 'n' OR k5 LIKE 'n' OR k6 LIKE '1' ";
$pattern = "~(?>\w++(?>\.\w++)?\h++LIKE\h++'[^']++'\h++OR\h++)*+\w++(?>\.\w++)?\h++LIKE\h++'[^']++'~";
$result = preg_replace($pattern, "##$0##",$sql);
echo '<pre>' . print_r($result, true) . '</pre>';
于 2013-04-24T21:58:42.090 に答える