如何让它不饿 - 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) 修饰符设置 在模式内或通过问题 在量词后面标记(例如 .*?
建议
/"['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
顺便说一句,这些是通过 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
在这一点上,我想知道那个/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 脚本,以防您好奇。
这似乎很武断。 所以我想知道这对你来说是否还不够好:
/"['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那样做成对的括号分隔符。
希望这有帮助!