以下是我想用PHP正则表达式解析的字符串示例:
this is first %@ variable <bpt>inside tags %@ variable</bpt> trailing %@ variable
我需要匹配的是%@
序列不在<bpt>
和</bpt>
之间。所以对于这个字符串模式应该返回2个匹配。
这是我到目前为止所做的:
%@(?!(?!<bpt).*\/bpt)
它没有按预期工作,只返回%@
的最后一次出现。在正则表达式模式中,我想检查匹配后没有</bpt>
结束标记,但是应该允许匹配后<bpt> ... </bpt>
的情况。
答案 0 :(得分:2)
你必须稍微改变你的正则表达式:
(?s)%@(?!(?:(?!<bpt>).)*<\/bpt>)
故障:
(?s) # Enable DOTALL flag
%@ # Match `%@`
(?! # A negative lookahead that means preceding match
# shouldn't come with next patterns which say:
(?:(?!<bpt>).)* # Without matching `<bpt>`
<\/bpt> # Match `</bpt>`
) # End of lookahead
但也有一种更优化的方法。由于正在使用PHP(PCRE),您可以使用名为SKIP
的回溯动词:
<bpt>.*?<\/bpt>(*SKIP)(*F)|%@
这样您就匹配整个bpt
标记(asap),然后告诉引擎跳过并尝试其他路径。
答案 1 :(得分:1)
这是我的解决方案,查看评论以获取解释
$str="this is first %@ variable1 <bpt>inside tags %@ variable</bpt> trailing %@ variable2 %@";
//strip put all contents inside <bpt>
$content = preg_replace('/<bpt>[^<]+<\/bpt>/i', '', $str);
//split string to words
$arr=explode(" ",$content);
//use array map for condition
//check for %@ and return preceding element after that
$variable_only=array_map(function ($a,$k)use($arr) { if($a==='%@') {return isset($arr[$k+1]) ? $arr[$k+1] :'' ; } }, $arr,array_keys($arr));
//remove blank arrays and reset keys
$variable_only=array_values(array_filter($variable_only));
print_r($variable_only);
输出
Array ( [0] => variable1 [1] => variable2 )