【问题标题】:regex: match pattern only if not preceded by special character / inside comment正则表达式:仅当前面没有特殊字符/内部注释时才匹配模式
【发布时间】:2023-03-05 22:04:01
【问题描述】:

我输入了类似以下示例的输入,并且只需要替换所有\input{.*} 命令,这些命令不是前面是%

输入是 LaTeX 代码,% 开始注释。这意味着当前行上% 之后的所有内容不应被解释为实际代码,而实际上只是一个注释。 (即使它看起来像代码)

示例输入:

this is \input{REAL.tex} real content    % \input{COMMENT.tex}
foo \input{REAL.tex} bar
\input{REAL.tex}
%\input{COMMENT.tex}
\input{REAL.tex} % comment

我当前的代码:

$r = "/^(?P<prefix>(?!.*%).*)\\\\input[{\s]+(?P<filename>.*?)[\s}](?P<suffix>.*)$/m";
$data = preg_replace($r, "REPLACED", $data);
echo $data . PHP_EOL;

CURRENT 示例输出:

this is \input{REAL.tex} real content    % \input{COMMENT.tex}
foo REPLACED bar
REPLACED
%\input{COMMENT.tex}
\input{REAL.tex}                         % comment

预期示例输出:

this is REPLACED real content            % \input{COMMENT.tex}
foo REPLACED bar
REPLACED
%\input{COMMENT.tex}
REPLACED                                 % comment

问题:不幸的是,我的正则表达式完全忽略了第一行和最后一行中的\inputs,因为中间有% 注释,由于前瞻断言(?!.*%)

问题:您是否发现了一种通过正则表达式实现所需输出的方法?第一行和最后一行的\input{REAL.tex} 也应该被替换。

【问题讨论】:

    标签: php regex pcre regex-lookarounds


    【解决方案1】:

    我刚刚意识到我不需要在这里全部使用环视!

    代码:

    $r = "/^(?P<prefix>[^%]*?)\\\\input\\{(?P<filename>[^}]*)\\}(?P<suffix>.*)$/m";
    $data = preg_replace($r, "\\1REPLACED\\3", $data);
    echo $data . PHP_EOL;
    

    输出:

    this is REPLACED real content % just a \input{COMMENT.tex}
    foo REPLACED bar
    REPLACED
    %\input{COMMENT.tex}
    REPLACED % comment
    

    【讨论】:

    • 不要忘记% 被转义的奇怪情况,即\% just a \input{REAL.tex} :)
    • @gwillie 哦,是的,对!非常感谢,这可能为我节省了另一个错误报告。
    【解决方案2】:

    你需要一个lookbehind来检查之前是否有%

    /(?<=%).*?\\\\input\{.+?\}/mis
    

    Lookbehind 语法是 (?&lt;=(your regex)),对于否定的lookbehind 它是 (?&lt;!(your regex))

    集成在您的代码中,如下所示

    $data = 'this is \input{REAL.tex} real content % just a \input{COMMENT.tex}
    foo \input{REAL.tex} bar
    \input{REAL.tex}
    %\input{COMMENT.tex}
    \input{REAL.tex} % comment';
    
    $r = "/(?<!%)([^%]*)\\\\input\{.+?\}/";
    $data = preg_replace($r, '$1REPLACED', $data);
    
    echo $newData . PHP_EOL;
    

    输出是

    this is REPLACED real content % just a \input{COMMENT.tex}
    foo \input{REAL.tex} bar
    REPLACED
    %\input{COMMENT.tex}
    REPLACED % comment
    

    【讨论】:

    • 感谢您的评论,但正如您所见,该命令不能直接以% 开头 - 两者之间可以有任意其他内容。看第一行的例子。请注意,lookbehind 不支持 PHPs PCRE 实现中的量词,所以像 (?&lt;!.*%) 这样的东西是不可能的 - 但可能会解决问题。
    • 将我上面回答中的正则表达式更正为/(?&lt;=%).*?\\\\input\{.+?\}/mis
    • 这不起作用。你能在我的例子中展示你将如何整合它吗?请注意,前缀和后缀也必须处理。
    • 输出错误,请仔细查看问题和/或我自己的答案
    • 然后给我看一个例子,输出Example input应该是怎样的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多