2013-04-24 2 views
0

Я хочу использовать preg_replace для строки, но хотя строка не соответствует, я получаю пустую строку в качестве возвращаемой строки.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' 
=> 

Странная вещь, регулярное выражение не даже матч. Я попытался максимально упростить строку, получив тот же результат. Я также могу добавить OR до конца-$. Но как только я уронил еще что-нибудь или добавлю. в противном случае, я получаю нормальное поведение и правильную замену.

Кто-нибудь видит, почему это происходит? Может быть, я допустил ошибку, которую я не вижу, может быть, это ошибка? Я потерял ...

(с использованием PHP версии 5.3.21 на LINUX сервере)

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

Edit:

Если это помогает, моя первоначально использовались данные были:

$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 (не пустая строка, как я узнал;) (Purpuse этого preg_replace является , Чтобы определить OR-условие в операторах SQL с LIKE «%» модели, чтобы удалить это ненужный OR-условие)

+1

'Если спичек , новый объект будет возвращен, иначе субъект будет возвращен без изменений или NULL, если возникла ошибка. '(http://php.net/manual/en/function.preg-replace.php) ... так что re, вероятно, является ошибкой с шаблоном. Главным может быть '[\ w]', который должен быть '\ w' в PHP. Тем не менее, есть еще несколько проблем с шаблоном. Каков желаемый результат? –

+0

С помощью якорей это выражение не требует, чтобы строка заканчивалась символом «OR» («ИЛИ» плюс два пробела)? – Wiseguy

+1

@Wiseguy это делает ...если он будет работать, он также заменит всю строку последним захватом. Вот что я имел в виду: «Есть еще несколько выпусков» ... но без желаемого результата, пытаясь исправить это просто дикие догадки –

ответ

3

Вашего регулярное выражение построено таким образом, что он потребляет огромное количество откатывается:.

echo preg_ last_ error() 

Урожайность 2 (PREG_BACKTRACK_LIMIT_ERROR)

Можно конечно увеличить BackTrack:

ini_set("pcre.backtrack_limit",100000000); 

... который сделал бы это regex не работает (поскольку он не совпадает), но он, по крайней мере, вернет исходную строку. Создание более эффективного регулярного выражения кажется более привлекательным, но для того, чтобы сделать удар, мне понадобится нужный вход &.

редактировать:

Глядя на него еще немного, я думаю, что это регулярное выражение может помочь вам на вашем пути немного:

$sql_A = preg_replace(
    "/(\w+ LIKE\s*('(\\\.|[^'\\\]|)*'|[^\s]+))/", 
    "##<$1>##", 
    $sql); 
+0

Oh. Я никогда не слышал о возвратах ... Думаю, мне нужно немного почитать об этом. Даже не знаю, что такое backtrack или почему он производится ... –

+0

Backtracks - это то, что движок регулярного выражения использует внутри, чтобы проверить соответствие (это именно то, что заставляет их работать). Основной проблемой в вашем регулярном выражении является ''?. *? '? ', Что на самом деле не ограничивает возможности совпадения, заставляя движок проверять множество перестановок перед тем, как приступить к правильному (или никому, как сейчас). – Wrikken

+1

@rItlha '[см. Здесь] (http://www.regular-expressions.info/catastrophic.html) –

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>'; 
+0

Это работает. Но я не понимаю части регулярного выражения. Насколько я понимаю, тильда используется как разделитель. Но есть (?> Какой-то взгляд вперед/сзади?(Не удается найти его с поиском, поскольку они просто пропускают эти буквы :) И что делает \ w ++? (имеет ++ особый смысл)? –

Смежные вопросы