как сделать regexp не голодным с кавычками?

как сделать его не голодным – preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+"/ui', $outStr, $matches);

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

 preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+?"/ui', $outStr, $matches); 

Жадный матч:

 "foo" and "bar" ^^^^^^^^^^^^^^^ 

Нежелательный матч:

 "foo" and "bar" ^^^^^ 

См .: http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

U (PCRE_UNGREEDY)

Этот модификатор инвертирует «жадность» квантификаторов, чтобы они не были жадными по умолчанию, но стали жадными, если следовать? ». Он несовместим с Perl. Его также можно установить с помощью (? U) модификатора в шаблоне или вопросительным знаком за квантификатором (например. *?).

ou предложил

 /"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+"/ui 

который я представляю, эквивалентен:

 /"[\pL\p{Nd}а-яА-ЯёЁ -_.+]+"/ui 

Чтобы показать людей, которые не используются в ASCII, если это не очевидно, используйте \x{⋯} последовательности, которые:

 /"[\pL\p{Nd}\x{430}-\x{44F}\x{410}-\x{42F}\x{451}\x{401} -_.+]+"/ui 

И используя именованные символы:

 /"[\pL\p{Nd}\N{CYRILLIC SMALL LETTER A}-\N{CYRILLIC SMALL LETTER YA}\N{CYRILLIC CAPITAL LETTER A}-\N{CYRILLIC CAPITAL LETTER YA}\N{CYRILLIC SMALL LETTER IO}\N{CYRILLIC CAPITAL LETTER IO} -_.+]+"/ui 

BTW, они создаются путем запуска их через скрипт uniquote , первый с использованием uniquote -x а второй – с помощью uniquote -v .

И да, я знаю или, по крайней мере, считаю, что PHP еще не поддерживает именованные символы, но это облегчает разговор. Кроме того, он гарантирует, что они не путают взгляды:

 U+0410 ‹А› \N{CYRILLIC CAPITAL LETTER A} U+0430 ‹а› \N{CYRILLIC SMALL LETTER A} U+0401 ‹Ё› \N{CYRILLIC CAPITAL LETTER IO} U+0451 ‹ё› \N{CYRILLIC SMALL LETTER IO} 

для:

 U+0041 ‹A› \N{LATIN CAPITAL LETTER A} U+0061 ‹a› \N{LATIN SMALL LETTER A} U+00CB ‹Ë› \N{LATIN CAPITAL LETTER E WITH DIAERESIS} U+00EB ‹ë› \N{LATIN SMALL LETTER E WITH DIAERESIS} 

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

 /"[\pL\p{Nd} -_.+]+"/ui 

В какой момент мне интересно об этом. Я не могу понять, какова его цель, так что просто напишите:

 /"[\pL\p{Nd} -_.+]+"/u 

Как уже упоминалось, замена максимального количества + для соответствующей минимальной версии +? , будет работать:

 /"[\pL\p{Nd} -_.+]+?"/u 

Однако меня беспокоит этот диапазон [ -_] , то есть \p{SPACE}-\p{LOW LINE} . Я нахожу этот очень своеобразный диапазон. Это означает, что любой из этих

 !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ 

Во-первых, вы снова включили буквы ASCII в капитал. Для другого вы опустили символы и знаки пунктуации:

 % unichars -g '\p{ASCII}' '[\pS\pP]' 'ord() < ord(" ") || ord() > ord("_")' ` U+0060 GC=Sk GRAVE ACCENT { U+007B GC=Ps LEFT CURLY BRACKET | U+007C GC=Sm VERTICAL LINE } U+007D GC=Pe RIGHT CURLY BRACKET ~ U+007E GC=Sm TILDE 

(Этот вывод выполняется из сценария unichars , если вам интересно).

Это кажется странно произвольным. Поэтому мне интересно, может ли это быть недостаточно для вас:

 /"[\pL\p{Nd}\s\pS\pP]+?"/u 

Теперь, когда я думаю об этом, эти два могут вызвать другие проблемы:

 U+0401 ‹Ё› \N{CYRILLIC CAPITAL LETTER IO} U+0451 ‹ё› \N{CYRILLIC SMALL LETTER IO} 

Это предполагает, что они находятся в форме NFC (образованной каноническим составом канонического разложения). Если бы у вас была вероятность, что вы имеете дело с данными, которые не были нормализованы для формы NFC, тогда вам придется учитывать

 NFD("\N{CYRILLIC CAPITAL LETTER IO}") => "\N{CYRILLIC SMALL LETTER IE}\N{COMBINING DIAERESIS}" NFD("\N{CYRILLIC SMALL LETTER IO}") => "\N{CYRILLIC CAPITAL LETTER IE}\N{COMBINING DIAERESIS}" 

И теперь у вас есть буквы без буквы!

 % uniprops "COMBINING DIAERESIS" U+0308 ‹◌̈› \N{COMBINING DIAERESIS} \w \pM \p{Mn} All Any Assigned InCombiningDiacriticalMarks Case_Ignorable CI Combining_Diacritical_Marks Dia Diacritic M Mn Gr_Ext Grapheme_Extend Graph GrExt ID_Continue IDC Inherited Zinh Mark Nonspacing_Mark Print Qaai Word XID_Continue XIDC 

Так что, возможно, вы действительно захотите:

 /"[\pL\pM\p{Nd}\s\pS\pP]+?"/u 

Если вы хотите ограничить свою строку содержащими только символы, которые написаны на латинских или кириллических сценариях (а не, скажем, на греческом или катакана), то вы добавили бы взгляд на этот эффект:

 /"(?:(?=[\p{Latin}\p{Cyrillic}])[\pL\pM\p{Nd}\s\pS\pP])+?"/u 

За исключением того, что вам также нужно, чтобы Common получал цифры и различные фразы и символы, и вам нужно Inherited для объединения меток, следующих за вашими письмами. Это подводит нас к следующему:

 /"(?:(?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}])[\pL\pM\p{Nd}\s\pS\pP])+?"/u 

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

 /"(?:(?!")(?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}])[\pL\pM\p{Nd}\s\pS\pP])+"/u 

Что усложняется, чтобы не работать в режиме /x :

 / " # literal double quote (?: ### This group specifies a single char with ### three separate constraints: # Constraint 1: next char must NOT be a double quote (?!") # Constraint 2: next char must be from one of these four scripts (?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}]) # Constraint 3: match one of either Letter, Mark, Decimal Number, # whitespace, Symbol, or Punctuation: [\pL\pM\p{Nd}\s\pS\pP] ) # end constraint group + # repeat entire group 1 or more times " # and finally match another double-quote /ux 

Если бы это был Perl, я бы написал, что с m{⋯}xu

 m{ " # literal double quote (?: ### This group specifies a single char with ### three separate constraints: # Constraint 1: next char must NOT be a double quote (?!") # Constraint 2: next char must be from one of these four scripts (?=[\p{Latin}\p{Cyrillic}\p{Common}\p{Inherited}]) # Constraint 3: match one of either Letter, Mark, Decimal Number, # whitespace, Symbol, or Punctuation: [\pL\pM\p{Nd}\s\pS\pP] ) # end constraint group + # repeat entire group 1 or more times " # and finally match another double-quote }ux 

Но я не знаю, можете ли вы делать парные, разделители брекетинга, подобные этому в PHP.

Надеюсь это поможет!