替换文件中特定文本中的换行符

时间:2018-12-13 10:09:28

标签: php regex

我们有一个防火墙,我们在其中使用PHP脚本处理配置,然后使其可在网站上查看。

今天发生了一个问题。问题在于评论字段。那里应该没有换行符。因此,我希望PHP在注释字段中删除换行符(用空格替换)。

我对正则表达式的经验有限,但是我已经使用regex101.comstackoverflow帖子的帮助建立了很多东西。由于某种原因,我似乎无法解决这个问题。

配置存储在一个文本文件中,如下所示:

config firewall policy
    edit 2
        set uuid 79123-123-51e6-bb5f-123f123df
        set srcintf "any"
        set dstintf "any"
        set srcaddr "h-host1" "h-host2" "h-host3"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set utm-status enable
        set logtraffic disable    
        set comments "This is a comment for this rule
 This is an additional comment for that rule"
        set ips-sensor "Sensor1"
    next
    edit 1
        set uuid f123-34ab-1dcf-a123dc123
        set srcintf "any"
        set dstintf "any"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set utm-status enable
        set logtraffic all
        set comments "This is a one line comment for a rule"    
        set ips-sensor "Sensor1"
    next
end

在此示例中,有1条注释带有换行符。 我尝试过的正则表达式存储在这里:https://regex101.com/r/0jaDjL/1/

它应该做的是先查找“设置注释” ,然后查找下一个引号,这样中间的换行符可以替换为一个空间。

所以这里:

        set comments "This is a comment for this rule
 This is an additional comment for that rule"

在这里成为这个:

        set comments "This is a comment for this rule This is an additional comment for that rule"

regex似乎可以在线上正确地抓取:https://regex101.com/r/0jaDjL/1/

但是不在我的环境中。例如,PHP不知道'g'参数。而且似乎找到了最后一个报价,而不是第一个下一个报价。

为了更好地了解会发生什么,我的编码现在看起来像这样:

<?php
function blaat($matches){
    echo '<pre>';
    echo PHP_EOL .'AAAAAAAAAAAAAAAAAAAA#'.$matches[0].'#AAAAAAAAAAAAAAAAAAAA';
    echo PHP_EOL .'BBBBBBBBBBBBBBBBBBBB#'.$matches[1].'#BBBBBBBBBBBBBBBBBBBB';
    echo PHP_EOL .'CCCCCCCCCCCCCCCCCCCC#'.$matches[2].'#CCCCCCCCCCCCCCCCCCCC';
    echo PHP_EOL .'DDDDDDDDDDDDDDDDDDDD#'.$matches[3].'#DDDDDDDDDDDDDDDDDDDD';
    echo PHP_EOL .'EEEEEEEEEEEEEEEEEEEE#'.$matches[4].'#EEEEEEEEEEEEEEEEEEEE';
    //echo PHP_EOL .'FFFFFFFFFFFFFFFFFFFF#'.$matches[5].'#FFFFFFFFFFFFFFFFFFFF';
}
$PathAndFile='C:\Temp\sys_config.txt';

preg_replace_callback(
    '/^(\s*?)(set comments ")(\X+)("$)/Um',
    'blaat',
    trim(file_get_contents($PathAndFile)) 
);

但是输出不是我想要的。

AAAAAAAAAAAAAAAAAAAA#
        set comments "This is a comment for this rule
 This is an additional comment for that rule"
        set ips-sensor "Sensor1"
    next
    edit 1
        set uuid f123-34ab-1dcf-a123dc123
        set srcintf "any"
        set dstintf "any"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set utm-status enable
        set logtraffic all
        set comments "This is a one line comment for a rule"#AAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBB#
        #BBBBBBBBBBBBBBBBBBBB
CCCCCCCCCCCCCCCCCCCC#set comments "#CCCCCCCCCCCCCCCCCCCC
DDDDDDDDDDDDDDDDDDDD#This is a comment for this rule
 This is an additional comment for that rule"
        set ips-sensor "Sensor1"
    next
    edit 1
        set uuid f123-34ab-1dcf-a123dc123
        set srcintf "any"
        set dstintf "any"
        set srcaddr "all"
        set dstaddr "all"
        set action accept
        set schedule "always"
        set service "ALL"
        set utm-status enable
        set logtraffic all
        set comments "This is a one line comment for a rule#DDDDDDDDDDDDDDDDDDDD
EEEEEEEEEEEEEEEEEEEE#"#EEEEEEEEEEEEEEEEEEEE

在注释字段中有关替换换行符的任何提示吗?

2 个答案:

答案 0 :(得分:1)

您需要在此处preg_replace_callback()的(嵌套)呼叫:

<?php

$regex = '~^\s*set comments\s\K"[^"]*"~m';

$data = preg_replace_callback($regex, function($match) {
    return preg_replace("~\R\s*~", " ", $match[0]);
},
$data);

echo $data;
?>

有关表达式,请参见a demo on ideone.coma demo on regex101.com


表达式的说明:

^             # match start of the line in multiline mode
\s*           # zero or more whitespaces
set comments  # set comments literally
\s            # whitespace
\K            # "forget" what's been matched thus far
"[^"]*"       # anything between double quotes ("...")


第一个表达式查找有问题的块,内部表达式用一个空格替换换行符和可能的连续空格。
要将所有连续空格替换为一个空格,请将内部表达式更改为:

return preg_replace("~\s+~", " ", $match[0]);

答案 1 :(得分:1)

您可以为此创建一个更简单的正则表达式,只需选择set comment "之后引号之间的所有文本,然后将所有新行替换为匹配项中的空格。 正则表达式的工作方式如下:https://regex101.com/r/AU2VJJ/1

这是您可以使用的php演示:

<?php
$text = <<<EOT
config firewall policy
    edit 2
        set srcintf "any" 
        set comments "This is a comment for this rule
 This is an additional comment for that rule"
        set ips-sensor "Sensor1"
    next
    edit 1
        set srcintf "any"
        set comments "This is a one l
ine comment for a rule"    
        set ips-sensor "Sensor1"
        set comments "This is a comment for this rule
 This is an additional comment for that rule
And one more."
    next
    edit 3
        set srcintf "any"
        set comments "This is a one l
ine comment for a rule"    
        set ips-sensor "Sensor1"
        set comments "This is a comment for this rule
Another comment
More comments
And more
And more
And one more."
    next
end
EOT;

$text =  preg_replace_callback('/(set comments ")([^"]+)(")/', function($matches) {
    // $matches[1] is `set comments"` text
    // $matches[2] is everything between `set comments"` and closing `"`
    // $matches[3] is closing `"`
    return $matches[1] . str_replace("\n", " ", $matches[2]) . $matches[3];
}, $text);
echo $text;