2015-12-07 3 views
2

Не будучи узнаваемым в шаблонах регулярных выражений и после прочтения всех вики и ссылок, я обнаружил, что у меня возникают проблемы с изменением шаблона для обнаружения слов и повышения яркости.regex case нечувствительный и с/без пробелов

Я нашел функцию на другой StackOverflow ответ, который сделал все, что было необходимо, но теперь я узнал, что он пропускает несколько вещей

Функция является:

function ParserGlossario($texto, $termos) { 

    $padrao = '\1<a href="#" class="termo">\2</a>\3'; 

    if (empty($termos)) { 
     return $texto; 
    } 

    if (is_array($termos)) { 
     $substituir = array(); 
     $com = array(); 

     foreach ($termos as $key => $value) { 
      $key = $value; 
      $value = $padrao; 
      // $key = '([\s])(' . $key . ')([\s\.\,\!\?\<])'; 
      $key = '([\s])(' . $key . ')([\s\.\,\!\?\<])'; 
      $substituir[] = '|' . $key . '|ix'; 
      $com[] = empty($value) ? $padrao : $value; 
     } 

     return preg_replace($substituir, $com, $texto); 

    } else { 

     $termos = '([\s])(' . $termos . ')([\s])'; 

     return preg_replace('|'.$termos.'|i', $padrao, $texto); 

    } 
} 

Некоторые слова не быть выделенные (те, отмеченные красными стрелками):

Words missing out

И я не знаю, если это поможет, но вот массив "терминов", который используется для поиска текста:

Words being searched

EDIT. Строка, которую ищут, представляет собой просто текст:

Abaxial Xxxxx acaule Acaule xxxxxx xxx; xxxxx xxx Абаксиальные esporos. abaxial

EDIT. Добавлена ​​PHP код скрипку

http://phpfiddle.org/main/code/079ad24318f554d9f2ba

Любая помощь? Я действительно не знаю много о регулярных выражениях ...

+0

Я предполагаю, что это строка html? Первый Abaxial, вероятно, не соответствует coz, он находится в начале строки и не имеет ведущего пространства. Показать фактическую строку ввода ('$ texto)', а не только ваши условия поиска. –

+0

Есть очень простой сайт, который дает вам отличные примеры и вы можете скопировать и вставить тестовый текст и попробовать RegEx здесь: (http://www.regexr.com) вы также можете скачать «Expresso 2.0», который представляет собой набор регулярных выражений, который имеет приличное количество предварительно загруженных регулярных выражений. –

+0

@MarcB: Извините, что не отправлял строку. Моя вина. Это просто плагин, следующий из выбора mysql. –

ответ

1

попробовать

$key = '(^|\b)(' . $key . ')\b'; 

insetad из

должен помочь. Ваши матчи по-прежнему будет во второй группе, но не будет никакого третьего, и я думаю, что первый не следует трогать, так что я считаю, что это

$padrao = '\1<a href="#" class="termo">\2</a>\3'; 

лучше быть

$padrao = '<a href="#" class="termo">$2</a>'; 

и забыл (извините): изменить

$substituir[] = '|' . $key . '|ix'; 

к

$substituir[] = '#' . $key . '#ix'; 

А также я хотел бы использовать строку

$com = empty($value) ? $padrao : $value; 

вместо массива, он не нужен в этом случае.

+0

И кстати, какая точка $ com [] = empty ($ value)? $ padrao: $ value; $ value никогда не пуст, так как ранее вы назначили ему строку из $ padrao – xmike

+0

Я действительно не знаю, что было предназначено для $ com [], но вы правы, это лучше, чем строка. Ваш ответ отлично поработал, и он очень хорошо разбирался во множественном числе слов. Еще один вопрос ... зачем менять $ substituir [] = '|' , $ key. '| IX'; по $ substituir [] = '#'. $ key. '#ix'; ? Не понял, что в выражении должна была использоваться ставка –

+1

metacharacter '|', поэтому разделители должны были быть изменены на что-то другое, я выбрал '#', вы можете выбрать что-то другое, если оно не выглядит симпатичным))) – xmike

1

Давайте посмотрим на значение $key, например, для элемента массива acaule.

([\s])(acaule)([\s\.\,\!\?\<]) 
  1. Есть 3 маркировочных групп, определяемых 3 паров ( ... ).

  2. Первая группа маркировки соответствует любому символу пробела. Если в начале строки нет символа пробела, такого как Abaxial, слово игнорируется.

    Ввод \s в класс символов, то есть в пределах [ ... ] не действительно нужен здесь, как \s сам класс символов. ([\s]) и (\s) равны.

  3. Вторая группа маркировки соответствует только слову из массива.

  4. В третьей маркировки группа соответствует

    • либо любой символ пробела,
    • или период,
    • или запятой,
    • или восклицательный знак,
    • или знаком вопроса , то есть стандартные знаки препинания,
    • или левую угловую скобку (из тега HTML или XML).


    Точка с запятой или двоеточие не сопоставляется, а другие символы без слов также игнорируются для положительного совпадения.

    Если в конце строки нет ни одного из этих символов, как для abaxial, поиск отрицательный.

    Кстати: ([\s.,!?<]) равно ([\s\.\,\!\?\<]), как только \ и ] (всегда) и - (в зависимости от положения) должны быть экранированы с обратной косой чертой в определении класса символ, который будет интерпретироваться как буквенный символ. Ну, [ также следует избегать с обратной косой чертой в пределах [ ... ] для удобства чтения.

Так что понятно, почему Abaxial в начале строки и abaxial в конце строки не совпадают.

Но почему Acaule не соответствует?

Ну вот, осталось слово acaule с пространством влево и вправо, как требуется для положительного совпадения. Таким образом, правое поле acaule уже было принято для этого позитивного матча. Поэтому для Acaule символа пробелов больше не осталось до этого слова.

Существует \b, что означает границу слова не соответствует любому символу, который может быть использован вместе с \W*? вместо ([\s]) и вместо ([\s\.\,\!\?\<]), чтобы избежать сопоставления подстрок в слове.

Возможно было бы что-то вроде

$key = '(\W*?)(\b' . $key . '\b)(\W*?)'; 

\W*? означает любые не буквенный символ 0 или более раз не жадный.

\W? означает любое не буквенный символ 0 или 1 раз и может быть также использован в первой и третьей группы захвата, если это лучше для замены.

Но какая правильная строка поиска зависит от того, что вы хотите в результате замены.

У меня нет PHP-интерпретатора, установленного вообще и, следовательно, вы не можете попробовать, что ваш PHP-код делает на замену, и, следовательно, то, что вы хотели бы видеть после замены, сделанного на приведенной строке примера.

+0

Прежде всего позвольте мне поблагодарить вас за подробное объяснение. Это было то, что я хотел, а просто дал мне решение. Я нахожу регулярные выражения по-настоящему запутанными, и такой ответ помогает!О решениях: первый ключ $, который вы мне даете, совсем не работает, а второй подчеркивает, что единичные термины, лишенные множественного числа, не подчеркиваются. Возьмем слово «esporos», например, в массиве поисковых запросов присутствуют слова «esporo» и «esporos». Это регулярное выражение подчеркивает часть «esporo», не подчеркивающую полную работу «esporos» –

+0

Итак, начальное первое предложение удалено и оставшееся предложение было изменено, чтобы убедиться, что вторая группа маркировки всегда содержит только цельное слово из массива и никогда не подстроку в более длинном слове, например, единственное слово во множественном числе. – Mofi