Php 如何匹配和解析具有不同形式的标记中的特定信息

Php 如何匹配和解析具有不同形式的标记中的特定信息,php,regex,pcre,Php,Regex,Pcre,我需要解析和处理从第三方以(UTF-8)文本文件的形式推送到我们的Web服务中的输入数据。输入文件包含一般形式的标记 <{ _N ('some_domain_id','this can be an arbitary string',{'a':'b','c':'d'}) }> -- -- -------------- ------------------------------ ----------------- -- ^ ^

我需要解析和处理从第三方以(UTF-8)文本文件的形式推送到我们的Web服务中的输入数据。输入文件包含一般形式的标记

<{ _N ('some_domain_id','this can be an arbitary string',{'a':'b','c':'d'}) }>
-- --   --------------   ------------------------------  -----------------  --
        ^                 ^                              ^
        i need to         |                              this part is 
        extract this      and this (payload)             optional
-不可识别,请注意括号,它们可以出现在数据字符串中的任何位置,甚至不需要进行平衡(例如:)


  • 无法识别,请注意_N元素最外层括号后的额外(可选)修饰符。修饰符可以由不同的字母(e、r、w)和任意字符串参数组成,链运算符
    |
    周围也可能有空格(例如:)
实验上,我已经尝试了一些其他正则表达式,但它们在扩展测试集中的一个或多个标记上总是失败,例如

  • /\u N\s*(\(\s*(?:\(?[^(]*?\s*)))+/
    -捕获修饰符大小写,但在相关字符串的括号中失败
所以我的问题是,我不是一个真正的正则表达式专家

  • 这个问题可以用正则表达式解决吗?如果可以,有人能给我一个正确的提示吗
  • 在香草PHP7+中是否有更好的解决方案,而无需安装/使用某些外部库

非常感谢您的帮助!

为什么您不能检索您需要的部件(在单引号中)

//示例1
$str='';
测试前费用($str);
//例2
$str='';
测试前费用($str);
//例3
$str='';
测试pregex($str,\'modifier');
函数测试_pregex($str,$optional=“{'a':'b','c':'d'}”){
$re='/\'([^\']*?)\'\'|(\{\'[^\']*?\'.+?})/m';
预匹配全部($re,$str,$MATCHS);
$matches=$matches[0];
var_导出(匹配项);
断言($matches[0]==“'some\u domain\u id'”);
assert($matches[1]==“‘这可以(是一个任意的)字符串’”);
断言($matches[2]==$optional);
}
输出将是所有三种情况,没有断言警告。然后您可以进一步处理您需要的内容。

您可以使用

<{\s*_N\s*\(\s*'([^\\']*(?:\\.[^\\']*)*)'\s*,\s*'([^\\']*(?:\\.[^\\']*)*)'\s*(.*?)}>

详细信息


好的,逗号分隔的值中有引号吗?也许类似的东西就可以了?如果你需要匹配括号或开始/结束括号,你需要一个标记器和上下文无关的语法分析器。解析这样的格式不适合正则表达式。我建议使用类似的库并描述你的输入通过BNF/CFG@Wiktor Stribiżew:非常感谢,但可能在“this can\”之类的值中有(转义)引号(可以是任意的)\“string”会破坏regexThat,这不是问题-谢谢,但如上所述,输入也可以包含转义引号,这些标记之间的内容完全不可预测。因此,您的解决方案还将匹配标记之间的大量段…这将不起作用“这些标记之间的内容完全不可预测”-现在我同意了e和其他评论。Regex将很难尝试断言给定的所有场景-您可能不知道标签之间会发生什么。一般来说,在经历了这些之后,我会同意,但正如我一开始不知道的那样,我倾向于快速替换,而不必更改或添加基本部分服务。但是请看@Wiktor Stribiżew comment,这一个通过了我所有的测试…虽然你当然是对的,但我仍然没有一个关于输入内容的全面数据库。
<{_N( 'some_domain_id' , 'this can  be an arbitary  string' {'a':'b','c':'d'})|e('modifier')}>
<{_N( 'some_domain_id' , 'this can  be an arbitary string')|e('modifier')}>
//example 1
$str = '<{_N( \'some_domain_id\' , \'this can ( be an arbitary ) string\',{\'a\':\'b\',\'c\':\'d\'})}>';
test_pregex($str);

//example 2
$str = '<{_N(\'some_domain_id\'      , \'this can ( be an arbitary ) string\'  ,{\'a\':\'b\',\'c\':\'d\'})}  >';
test_pregex($str);

//example 3
$str = '<{_N( \'some_domain_id\' , \'this can ( be an arbitary ) string\')|e(\'modifier\')}>';
test_pregex($str, '\'modifier\'');

function test_pregex($str, $optional = "{'a':'b','c':'d'}") {
    $re = '/\'([^\']*?)\'|(\{\'[^\']*?\'.+?})/m';
    preg_match_all($re, $str, $matches);
    $matches = $matches[0];
    var_export($matches);   
    assert($matches[0] == "'some_domain_id'");
    assert($matches[1] == "'this can ( be an arbitary ) string'");
    assert($matches[2] == $optional);
}
<{\s*_N\s*\(\s*'([^\\']*(?:\\.[^\\']*)*)'\s*,\s*'([^\\']*(?:\\.[^\\']*)*)'\s*(.*?)}>