2011-10-19 33 views
5

我仍然在学习很多关于PHP的知识,字符串变化是我感兴趣的东西。我之前使用过preg_match来验证电子邮件地址或者只是查询查询。preg_match_all()如何处理字符串?

我刚刚从这篇文章What's wrong in my regular expression?来,很好奇为什么preg_match_all函数产生2个字符串,1个/一些字符被剥离,然后另一个w /所需的输出。

从我对函数的理解中可以看出,它使用RegEx来逐个字符地检查字符串以评估如何处理它。这个RegEx的结构是否可以绕过第一个数组入口并产生所需的结果?

,所以你不必去其他线程

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

for($i=0;$i<count($newStr[0]);$i++) 
{ 
    echo $newStr[0][$i].'<br>'; 
} 

echo '<br><br><br>'; 

for($i=0;$i<count($newStr[1]);$i++) 
{ 
    echo $newStr[1][$i].'<br>'; 
} 

这将输出

^强尼〜
^史密斯〜
^[email protected]~


强尼
史密斯
[email protected]

我很好奇,如果2数组项的原因是由于该字符串的原始sytax或如果它是该函数的正常处理响应。对不起,如果这不应该在这里,但我真的很好奇这是如何工作的。

感谢, 布罗迪

+0

输出将始终包含整个匹配项和表达式中每个捕获组的条目。 –

+0

不是一个答案,但有趣的是这里需要注意'PREG_SET_ORDER'标志,它将返回一个更简单的结果列表。虽然你不能删除整个匹配的'[0]'数组项,你可以在正则表达式中使用'\ K'来去除它的内容。 – mario

回答

2

这是对的preg_match和preg_match_all规范的行为 - 在“匹配的值”数组中的第一个字符串是由正则表达式模式捕获的完整字符串。随后的数组值是“捕获组”,其存在取决于正则表达式模式中()对的位置/位置。

在你的正则表达式的情况下,/\^([^^]*?)\~/,全匹配的字符串会

^ Jony ~ 
|  |  | 
^ ([^^]*?) ~ -> $newstr[0] = ^Jony~ 
       -> $newstr[1] = Jony (due to the `()` capture group). 
+0

我明白了,所以它所做的第一件事情是找到文本以w/^开始并以〜结尾,然后()中的第二个表达式将^减去〜后面的所有内容。我想,如果[^^] *,好奇心会获得最好的结果?告诉它在'^'后抓取文本,为什么不抓住'〜'? – Brodie

+0

它确实存在,但'〜'不在捕获组内,所以它只会出现在'[0]'部分。您可以将整个正则表达式模式视为一个捕获组本身,以便将该虚拟捕获存储在'[0]'中,然后使用'()'显式创建的任何捕获进入[1],[2], etc .. –

+0

'[^^] *?'以非贪婪的方式(?)转换为不是^([^^])的许多字符(*,'0或更多')。 –

0

[0]包含整个匹配,而[1]只有一部分(要提取的部分)...... 你可以做var_dump($newStr)看到阵列结构,你就看着办吧。

$str = 'text^name1^Jony~text^secondname1^Smith~text^email1^example- 
     [email protected]~'; 

preg_match_all('/\^([^^]*?)\~/', $str, $newStr); 

$newStr = $newStr[1]; 
foreach($newStr as $key => $value) 
{ 
    echo $value."\n"; 
} 

这将导致......(怪异的结果,没有修改的表达)

Jony 
Smith 
example- 
     [email protected] 
1

随着manual州,这是预期的结果(默认PREG_PATTERN_ORDER标志)。 $newStr的第一个条目包含所有全模式匹配,下一个结果是第一个子模式的所有匹配(括号中)等等。

+0

现在有道理啊...谢谢你的回答 – Brodie

1

preg_match_all的结果中的第一个数组返回匹配您传递给preg_match_all()函数的整个模式的字符串,在您的情况下为/ \ ^([^^] *?)\〜/。结果中的后续数组包含模式中括号的匹配项。也许更容易用一个例子就明白了:

$string = 'abcdefg'; 
preg_match_all('/ab(cd)e(fg)/', $string, $matches); 

的$匹配阵列将

array(3) { 
    [0]=> 
    array(1) { 
    [0]=> 
    string(7) "abcdefg" 
    } 
    [1]=> 
    array(1) { 
    [0]=> 
    string(2) "cd" 
    } 
    [2]=> 
    array(1) { 
    [0]=> 
    string(2) "fg" 
    } 
} 

第一个数组将包含整个模式的匹配,在这种情况下,“ABCDEFG”。第二个数组将包含第一组括号的匹配,在本例中为'cd'。第三个数组将包含第二组括号的匹配,在本例中为'fg'。

2

这个RegEx的结构可以绕过第一个数组入口,并产生所需的结果吗?

绝对。使用assertions。此正则表达式:

preg_match_all('/(?<=\^)[^^]*?(?=~)/', $str, $newStr); 

结果:

Array 
(
    [0] => Array 
     (
      [0] => Jony 
      [1] => Smith 
      [2] => [email protected] 
     ) 

) 
0

只要你有问题,想象的preg_match_all你应该使用的评估像preg_match_all tester @ regextester.net

功能这说明你的结果实时和你可以配置结果顺序,元指令,偏移量捕捉等等。