如何让它不饿 - preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+"/ui', $outStr, $matches);
答案 0 :(得分:11)
你的意思是非贪婪,因为找到最短的比赛而不是最长的比赛?默认情况下,*
,+
和?
量词是贪婪的,并且会尽可能匹配。在它们后面添加一个问号,使它们不贪婪。
preg_match_all('/"[\p{L}\p{Nd}а-яА-ЯёЁ -_\.\+]+?"/ui', $outStr, $matches);
贪婪的比赛:
"foo" and "bar"
^^^^^^^^^^^^^^^
非贪婪的比赛:
"foo" and "bar"
^^^^^
答案 1 :(得分:3)
请参阅:http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php
U(PCRE_UNGREEDY)
这个修饰语反映了量词的“贪婪” 他们默认不贪心 但如果紧随其后会变得贪婪吗?它 与Perl不兼容。它可以 也可以通过(?U)修改器设置来设置 在模式内或通过问题 在量词后面标记(例如。*?)。
答案 2 :(得分:2)
建议
/"[\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 script运行它们产生的,第一个使用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
此时我想知道/i
。我看不出它的目的是什么,所以只写:
/"[\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 script。)
这似乎很奇怪。所以我想知道这对你来说是否不够好:
/"[\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
来获取数字和各种puntuation和符号,以及
你需要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中使用这样的配对包围分隔符。
希望这有帮助!