如何在最后一个嵌套的`(`和`)`之间获取字符串,但是如果没有字符串,那么获取直接父``()之间的字符串?

时间:2016-10-03 05:18:48

标签: php regex

假设我有这个字符串:

date_format(from_days(datediff(now(),api.dob)),'%y')+0

我想检查嵌套最多的()的内容,上面示例中的内容是now(),但如果内部没有字符串,请获取下一个api.dob。如果嵌套的内容为空,则外部()的顺序相同。 我怎么能用PHP做到这一点? 我问了同样的问题link 但是如果嵌套的一个内容为空,那么应该按顺序获取下一个内容。

1 个答案:

答案 0 :(得分:2)

我建议使用像

这样的条件正则表达式
\w+\((?<in>[^()]+)?\)(?(in)|,\K[^,()]+)

请参阅regex demo

详细

  • \w+ - 一个或多个字母/数字/下划线
  • \( - 文字(
  • (?<in>[^()]+)? - 一个命名组&#34; in&#34;捕获除()
  • 以外的1个或多个字符
  • \) - 文字)
  • (?(in) - 条件检查in组是否匹配。如果确实如此,那就什么都不匹配
  • | - 其他
  • ,\K - 匹配,,然后省略到目前为止匹配的全文
  • [^,()]+ - 匹配,()以外的任何1个以上的字符。 (不确定逗号,请根据需要进行调整)
  • ) - 条件
  • 的结尾

PHP demo

$re = '/\w+\((?<in>[^()]+)?\)(?(in)|,\K[^,()]+)/';
$str = "date_format(from_days(datediff(now(),api.dob)),'%y')\ndate_format(from_days(datediff(now('here'),api.dob)),'%y')";
preg_match_all($re, $str, $matches);
print_r($matches[0]); // => Array ( [0] => api.dob [1] => now('here') )

更新

由于您需要的子字符串可能位于实际为匹配选择设置条件的子字符串之前,因此您需要实际捕获您感兴趣的所有部分并检查匹配的组。

我建议以下变体:

(?:(?<res1>\w+(?:\.\w+)+)[^()]*\()?\b(?<res2>\w+\((?<in>[^()]+)?\))(?(in)|,(?<res3>\w+(?:\.\w+)+))?

请参阅regex demo

PHP demo

$re = '/(?:(?<res1>\w+(?:\.\w+)+)[^()]*\()?\b(?<res2>\w+\((?<in>[^()]+)?\))(?(in)|,(?<res3>\w+(?:\.\w+)+))?/';
$strs = array('date_format(from_days(datediff(now(),api.dob)),\'%y\')',
'date_format(from_days(datediff(now(\'here\'),api.dob)),\'%y\')',
'if(awe.date_to >= date_sub(now(),interval 3 year),\'yes\',\'no\')"');

foreach ($strs as $str) {
    if (preg_match($re, $str, $match)) {
        if (!empty($match["res3"])) {
            echo $match["res3"] . PHP_EOL;
        }
        else if (!empty($match["res1"])) {
            echo $match["res1"] . PHP_EOL;
        }
        else echo $match["res2"] . PHP_EOL;
    };
}