оптимизация php PCRE Regex - PullRequest
       7

оптимизация php PCRE Regex

1 голос
/ 22 ноября 2010

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

Вот моя строка ввода:

$str = 'Some text
spanned on
several lines
txt_to_grab1 fixed_text1 txt_to_grab2
Full line to grab
txt_to_grab3 fixed_text2 txt_to_grab4
Some text after';

Iя пытаюсь перехватить строки от «txt_to_grab1» до «txt_to_grab4», но только слова «txt_to_grabX» и строку «Full line to grab».
Я хочу сохранить все нетронутым до и после (то есть разрывы строк), но удалите разрывы строк внутри строк, которые я беру (так как каждая строка будет <tr>, которая войдет в HTML-таблицу).

Шаблоны регулярных выражений / замените найденное соответствие:

$find = "#(?<=\n)(.*?) fixed_text1 (.*?)(\n.*?\n)(.*?) fixed_text2 (.*?)(\n)#i";
$replace = '"$1" && "$2" grabbed.$3"$4" && "$5" grabbed.$6';   

$find = "#(.*)(?<=\n)(.*?) fixed_text1 (.*?)(\n)(.*)(?<=\n)(.*?) fixed_text2 (.*?)(\n.*)#is";
$replace = '$1"$2" && "$3" grabbed.$4$5"$6" && "$7" grabbed.$8';

Вопросы:

Все вопросы можно суммировать следующим образом: существуют ли лучшие / короткие / быстрые шаблоны?

  • как заставить шаблоны работать с любой из \ r\ n или \ n?Я читал где-то в стеке, что (\ r? \ N) было бы решением, но я не знаю, как их использовать в виде сзади.Например, следующие шаблоны работают, но они мне не нравятся (грязные, так как в видоискателях используются только \ n, могут привести к неожиданным результатам):

    "#(?<=\n)(.*?) fixed_text1 (.*?)(\r?\n.*?\r?\n)(.*?) fixed_text2 (.*?)(\r?\n)#i"
    "#(.*)(?<=\n)(.*?) fixed_text1 (.*?)(\r?\n)(.*)(?<=\n)(.*?) fixed_text2 (.*?)(\r?\n.*)#is";
    
  • еще лучше, какиспользовать модификатор "s", чтобы удалить все разрывы строк из шаблона, чтобы иметь возможность использовать (. *?), но все еще захватывать то, что я хочу?Границы слова?

  • полезен / полезен многострочный режим (модификатор m)?

Мне бы очень хотелось, чтобы регулярные выражения были объяснены, если вы предоставите некоторые:)

1 Ответ

1 голос
/ 22 ноября 2010

Вам не нужно смотреть за этим. Просто используйте привязку начала строки в начале вашего регулярного выражения и привязку конца строки в конце (это ^ и $ в многострочном режиме). Чтобы сопоставить разделители строк в середине, вы можете использовать (?:\r\n|[\r\n]), общую идиому для трех наиболее распространенных стилей разделителя строк: \n, \r или \r\n.

Что касается модификатора s (например, «однострочный» или «DOT_ALL»), он вам также не нужен. Все, что он делает, это позволяет метасимволу точки совпадать с разделителями строк, а также со всеми остальными символами, что не приносит вам никакой пользы. Вы хотите, чтобы прекратил сопоставление, когда он достигнет разрывов строк, поэтому вы можете исключить их из ваших захватов.

Вот демоверсия:

$pattern='#^(.*?) fixed_text1 (.*)(?:\r\n|[\r\n])(.*)(?:\r\n|[\r\n])(.*?) fixed_text2 (.*)$#im';

preg_match($pattern, $source, $m);

echo "$m[1] && $m[2] grabbed.\n";
echo "$m[3]\n";
echo "$m[4] && $m[5] grabbed.\n"; 

выход:

txt_to_grab1 && txt_to_grab2 grabbed.
Full line to grab
txt_to_grab3 && txt_to_grab4 grabbed.

Смотрите его в действии на ideone.com

...