10

这是我的字符串:

address='St Marks Church',notes='The North East\'s premier...'

我用来抓取各个部分的正则表达式match_all

'/(address|notes)='(.+?)'/i'

结果是:

地址 => 圣马可教堂
笔记 => 东北部\

我怎样才能让它忽略注释的 \' 字符?

4

3 回答 3

5

不知道你是用heredoc还是双引号包裹你的字符串,但一种不那么贪婪的方法:

$str4 = 'address="St Marks Church",notes="The North East\'s premier..."';
preg_match_all('~(address|notes)="([^"]*)"~i',$str4,$matches);
print_r($matches);

输出

Array
(
    [0] => Array
        (
            [0] => address="St Marks Church"
            [1] => notes="The North East's premier..."
        )

    [1] => Array
        (
            [0] => address
            [1] => notes
        )

    [2] => Array
        (
            [0] => St Marks Church
            [1] => The North East's premier...
        )

)

preg_split 的另一种方法:

//split the string at the comma
//assumes no commas in text
$parts = preg_split('!,!', $string);
foreach($parts as $key=>$value){
    //split the values at the = sign
    $parts[$key]=preg_split('!=!',$value);
    foreach($parts[$key] as $k2=>$v2){
        //trim the quotes out and remove the slashes
        $parts[$key][$k2]=stripslashes(trim($v2,"'"));
    }
}

输出如下所示:

Array
(
    [0] => Array
        (
            [0] => address
            [1] => St Marks Church
        )

    [1] => Array
        (
            [0] => notes
            [1] => The North East's premier...
        )

)

超慢老派方法:

$len = strlen($string);
$key = "";
$value = "";
$store = array();
$pos = 0;
$mode = 'key';
while($pos < $len){
  switch($string[$pos]){
    case $string[$pos]==='=':
        $mode = 'value';
        break;
    case $string[$pos]===",":
        $store[$key]=trim($value,"'");
        $key=$value='';
        $mode = 'key';
        break;
    default:
        $$mode .= $string[$pos];
  }

  $pos++;
}
        $store[$key]=trim($value,"'");
于 2013-06-06T19:58:24.780 回答
2

因为您发布了您正在使用的帖子,match_all并且您的个人资料中的顶部标签是phpand wordpress,所以我认为假设您正在使用preg_match_all()php 是公平的。

以下模式将匹配构建所需关联数组所需的子字符串:

生成完整字符串匹配和 1 个捕获组的模式:

  1. /(address|notes)='\K(?:\\\'|[^'])*/(166步,演示链接
  2. /(address|notes)='\K.*?(?=(?<!\\)')/(218步,演示链接

生成 2 个捕获组的模式:

  1. /(address|notes)='((?:\\\'|[^'])*)/(168步,演示链接
  2. /(address|notes)='(.*?(?<!\\))'/(209步,演示链接

代码:(演示

$string="address='St Marks Church',notes='The North East\'s premier...'";

if(preg_match_all("/(address|notes)='\K(?:\\\'|[^'])*/",$string,$out)){
    $result=array_combine($out[1],$out[0]);
}
var_dump($result);

echo "\n---\n";

if(preg_match_all("/(address|notes)='((?:\\\'|[^'])*)/",$string,$out,PREG_SET_ORDER)){
    $result=array_combine(array_column($out,1),array_column($out,2));
}
var_dump($result);

输出:

array(2) {
  ["address"]=>
  string(15) "St Marks Church"
  ["notes"]=>
  string(28) "The North East\'s premier..."
}

---
array(2) {
  ["address"]=>
  string(15) "St Marks Church"
  ["notes"]=>
  string(28) "The North East\'s premier..."
}

模式#1 和#3 使用替代项来允许非撇号字符或不带反斜杠的撇号。

模式#2 和#4(使用 php demo实现时需要额外的反斜杠)使用环视来确保反斜杠前面的撇号不会结束匹配。

一些注意事项:

  • 使用捕获组、备选方案和环视会降低模式效率。限制这些组件的使用将提高性能。使用否定字符类通常可以提高性能。

  • 尝试减少捕获组时,使用\K(重新启动全字符串匹配)很有用,它会减小输出数组的大小。

于 2017-11-18T12:59:35.373 回答
1

您应该匹配一个没有反斜杠的结束引号,因此:

(address|notes)='(.*?)[^\\]'

[^\\]会强制紧接在 ' 字符之前的字符不是反斜杠。

于 2013-06-06T19:49:30.467 回答