【问题标题】:How to find a string match within a subject for this pattern {{ @sql( query ) }}如何在此模式的主题中查找字符串匹配 {{ @sql( query ) }}
【发布时间】:2016-05-05 04:03:50
【问题描述】:

我正在尝试使用 php 查找模式匹配。

我的字符串包含类似这样的内容

{{ @sql( select [name] from [table] where [col1] = 50 AND [col2] = :alt_id_1 AND [col3] = :id  ) }}

我需要返回以下数据

  1. 字符串匹配的部分
  2. {{@sql()} 之间的字符串
  3. 任何以冒号开头的关键字:

例如,如果我有以下字符串

$subject = 'Hello This is a test. The value found is "{{ @sql( select [name] from [table] where [col1] = 50 AND [col2] = :alt_id_1 AND [col3] = :id  ) }}".';

那么对于第一个子弹,我需要返回{{ @sql( select [name] from [table] where [col1] = 50 AND [col2] = :alt_id_1 AND [col3] = :id ) }}

对于第二个子弹,我需要返回 select [name] from [table] where [col1] = 50 AND [col2] = :alt_id_1 AND [col3] = :id

对于最后一个项目符号,我将返回一个包含 :alt_id_1:id 的数组

这是我尝试过的

$pattern = '/\{\{\s*+@sql(*)+\s*+\}\}/i';
$matches = [];
preg_match_all($pattern, $subject, $matches, PREG_OFFSET_CAPTURE);
echo '<pre>';
print_r($matches );
echo '</pre>';

但它给了我一个例外

preg_match_all(): Compilation failed: nothing to repeat at offset 13

【问题讨论】:

    标签: php regex preg-match preg-match-all


    【解决方案1】:

    您无法使用 PREG 和大多数其他正则表达式语法捕获重复的子模式

    所以,你可以试试这个:

    $pattern = '/\{\{\s*+@sql\((.+(\:[^ ]+))+.*\)+\s*+\}\}/i';
    

    preg_match_all 将捕获仅最后一个子模式。 如果您事先知道所有主题将具有完全相同数量的:xxx 子字符串,则可以这样设置模式:

    $pattern = '/\{\{\s*+@sql\((.+(\:[^ ]+).+(\:[^ ]+).*)\)+\s*+\}\}/i';
    

    否则,你必须运行两个不同的preg_match

    $pattern1 = '/\{\{\s*+@sql\((.+)\)+\s*+\}\}/i';
    $pattern2 = '/:[^ ]+/i';
    
    preg_match    ( $pattern1, $subject,       $matches,   PREG_OFFSET_CAPTURE );
    preg_match_all( $pattern2, $matches[1][0], $repeating, PREG_OFFSET_CAPTURE );
    

    eval.in demo

    编辑:

    来自官方PHP Documentation

    当重复捕获子模式时,捕获的值是匹配最终迭代的子字符串

    【讨论】:

    • 非常感谢您这样做
    【解决方案2】:

    括号是特殊字符。所以如果你想要文字括号,你应该转义它们

    $pattern = '/\{\{\s*+@sql\([^\)]*\)\s*+\}\}/i';
    

    (*)+ 更改为\([^\)]*\)

    编译错误来自 )+,因为它无法将 ) 识别为中继器 (+) 的有效字符。

    【讨论】:

    • 这解决了错误并找到了整个字符串,即项目符号 1。如何让项目符号 2 和 3 脱离相同的模式?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-19
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多