2016-08-17 7 views
1

Я вытаскиваю подмодели автомобиля из БД, и я строю свое регулярное выражение на лету.Проблема с регулярным выражением с подмоделими автомобилей

Вот пример строки поиска: EX-L Седан 4-дверный

Вот мое регулярное выражение: preg_match ("/ LX | EX | EX-L | LX-P | LX- S/Ui ", $ input_line, $ output_array);

По какой-то причине выход EX, а не EX-L, как и предполагалось. Может кто-нибудь объяснить, почему?

+0

Изменить порядок. – revo

+1

@revo правильно; поместите свои самые длинные термины с первым запуском, например, 'EX-L' перед' EX', потому что совмещение чередования останавливается на первом совпадающем шаблоне в порядке слева направо – Bohemian

+0

@ user1029829 Ваш вопрос кажется нерешенным/оставленным, пожалуйста, отметьте один из ответы ниже, как принято, чтобы ваш вопрос можно было положить на отдых. Кроме того, рассмотрите возможность редактирования своего заголовка на то, что лучше описывает проблему с регулярным выражением (и не упоминает _car submodels_) - возможно, «Неожиданное соответствие альтернативному регулярному выражению» или что-то в этом роде. Наличие названия с соответствующими ключевыми словами привлечет лучшее внимание к результатам поиска. Наконец, добавьте 'php' и' regex-alternation' в свой список тегов в вопросе. Лучшие вопросы + Лучшие ответы = Лучше SO – mickmackusa

ответ

2

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

Кроме того, в вашем шаблоне нет квантификаторов, поэтому модификатор /U является избыточным.

Таким образом, вы можете использовать

/EX-L|LX-P|LX-S|LX|EX/i 

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

/EX(-L)?|LX(-[PS])?/i 
0

Как уже отмечалось, причиной этого нежелательного исхода, так как движок регулярных выражений рад иметь первый вариант и бежать за дверью, так как ваша модель не имеет якоря (например: ^, $ и некоторые другие менее известные). Это то же самое короткое замыкание, которое вы увидите в условиях php's if($x || $y); если $x истинно, нет необходимости оценивать дальше. Но достаточно об этом ...

Я хотел бы предложить дополнительную логику, которая, по моему мнению, относится к вашему делу/вопросу.

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

  1. Пользователь определяет, какие подстроки/ключевые слова они хотят искать.

    $strings=array('LX','EX','EX-L','LX-P','LX-S'); // array of substrings in any order

  2. Как уже упоминалось ранее, вам нужно более длинные строки предшествуют более короткие с одинаковыми исходными символами.

    rsort($strings); // sort DESC, longer strings precede shorter strings when leading characters match

  3. Трубные все строки в один шаблон регулярных выражений с Implode().

    $piped_regex='/\b(?:'.implode('|',$array).')\b/i'; // word boundaries ensure the string is not part of a larger word; remove if not desired // pattern: /\b(?:LX-S|LX-P|LX|EX-L|EX)\b/i

    Хотя программно конденсационные ваши подобные строки в краткой схеме, что Wiktor рекомендуется возможно, это, вероятно, не стоит усилий, с узорами на лету.

  4. Завершите выполнение preg_match() как обычно.

    $input_line='EX-L Sedan 4-Door'; 
    if(preg_match($piped_regex,$input_line,$output_array)){ 
        var_export($output_array); 
    } 
    // output: array(0=>'EX-L') 
    

Я надеюсь, ступая этот метод является полезным для вас и будущего SO читателей.

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

  • Нет связанных вопросов^_^