Заменить перенос строки в определенном фрагменте текста в файле - PullRequest
0 голосов
/ 13 декабря 2018

У нас есть брандмауэр, который обрабатывает конфигурацию с помощью PHP-скрипта, а затем делает его доступным для просмотра на веб-сайте.

Сегодня возникла проблема.Проблема заключается в поле комментариев.Там не должно быть разрыва строки там.Поэтому я обратился к PHP, чтобы удалить перевод строки (замените его пробелом) в поле комментариев.

Мой опыт работы с регулярными выражениями ограничен, но я создал довольно много, используя regex101.com и помощь stackoverflow сообщений.По какой-то причине эту проблему я не могу решить.

Конфигурация хранится в текстовом файле, который выглядит следующим образом:

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 голосов
/ 13 декабря 2018

Вы можете сделать более простое регулярное выражение для этого, просто выделите весь текст между кавычками после 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;
0 голосов
/ 13 декабря 2018

Вам нужен (вложенный) вызов 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;
?>

См. демонстрацию на ideone.com и демо на 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]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...