如何修改正则表达式以排除与双引号包围的短语中包含的冒号匹配?

How to modify a regex to exclude matching against a colon contained in a phrase surrounded by double quotes?

这是我当前的正则表达式(用于解析 iCal 文件):

/([^:]+)[:|(;)]([\w\W]*)/

使用preg_match()的当前输出是这样的:

//Output 1
Array
(
    [0] => DTEND;TZID="Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London":20150601T073000
    [1] => DTEND;TZID="Greenwich Mean Time 
    [2] =>  Dublin, Edinburgh, Lisbon, London":20150601T073000
)

我想修改我的正则表达式以输出这个(即忽略冒号,如果它是用双引号括起来的短语的一部分 - 我想我需要回顾一下,而且永远只能找到一个冒号,因为它是分隔符):

//Output 2
Array
(
    [0] => DTEND;TZID="Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London":20150601T073000
    [1] => DTEND;TZID="Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London"
    [2] => 20150601T073000
)

正则表达式中的分号在那里,因为有时我要查找的冒号可能在下一行,因为定义了多个属性 (;TZID="Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London"),所以在这种情况下,我在分号处打断。有关信息,一次一行读取 iCal 文件。

(.*?)(?::(?=(?:[^"]*"[^"]*")*[^"]*$)|;(?=[^:]*$))([\w\W]*)

您可以尝试 this.See 演示。

https://regex101.com/r/pG1kU1/9

您需要一个基于 SKIP-FAIL trick 的正则表达式,它可以安全地匹配其他模式之外的模式。但是,我找不到 1-regex 解决方案:(。您可以使用主要的解决方案来匹配引号字符串外的冒号,如果它无法为您获取超过 1 个元素的数组,请使用另一个:

"(?:[^"](?:\.[^"]+)?)+"(*SKIP)(*FAIL)|:

 "(?:[^"](?:\.[^"]+)?)+"(*SKIP)(*FAIL)|;

"(?:[^"](?:\.[^"]+)?)+" 将安全地匹配任何转义实体(如果有)。

$re = '#"(?:[^"](?:\.[^"]+)?)+"(*SKIP)(*FAIL)|:#'; 
$str = "DTEND;TZID=\"Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London\":20150601T073000";
//$str = "DTEND;TZID=\"Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London\";20150601T07300001T073000"; 
$arr = preg_split($re, $str);
if (count($arr)>1){
  print_r($arr);
}
else {
 $re2 = '#"(?:[^"](?:\.[^"]+)?)+"(*SKIP)(*FAIL)|;#';
 $arr2 = preg_split($re2, $str);
 if (count($arr2)>1){
  print_r($arr2);
 }
 else {
  echo "No matches";
 }
}

IDEONE Demo

再试一次(不确定):

"(?:[^"](?:\.[^"]+)?)+"(*SKIP)(*FAIL)|(?!.*:);(?=[^:]*$)|(?!.*;):(?=[^;]*$)

See demo