Многострочная строка командной строки Perl

Я пытаюсь заменить текст в многострочном файле с помощью командной строки perl. Я использую Ubuntu Natty.

Ниже приведено содержимое моего текстового файла (называемого test.txt):

[mysqld]
#
# * Basic Settings
#

#
# * IMPORTANT
#   If you make changes to these settings and your system uses apparmor, you may
#   also need to also adjust /etc/apparmor.d/usr.sbin.mysqld.
#

user            = mysql
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
skip-external-locking

Ниже приведена моя команда perl:

perl -i -pe "s/(\[mysqld\][^\^]+)/\1\nsometext/g" test.txt

Однако вместо замены всего текста в файле ниже я получаю следующее:

[mysqld]

sometext#
# * Basic Settings
#

#
# * IMPORTANT
#   If you make changes to these settings and your system uses apparmor, you may
#   also need to also adjust /etc/apparmor.d/usr.sbin.mysqld.
#

user            = mysql
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
skip-external-locking
#

Я пробовал Regex в RegexBuddy для Perl, и он соответствует всем в текстовом файле, но по какой-то причине он не работает с использованием perl в командной строке.

Буду признателен за помощь.

Спасибо заранее.

Ответ 1

Вы читаете файл по очереди, поэтому только первая строка соответствует вашему регулярному выражению. То, что вы хотите сделать - если вы действительно хотите удалить большую часть контента, - это разделить файл с помощью параметра -0, например. -0777. Это обработка окончания строки, а 777 - это просто номер, используемый условным обозначением, как восьмеричное число, достаточно большое, чтобы вызвать разрывы файлов.

perl -0777 -i -pe 's/(\[mysqld\][^\^]+)/$1\nsometext/g' test.txt

Кроме того, я заменил ваши кавычки. Если вы находитесь в * nix, который, кажется, вам нужен, одинарные кавычки предпочтительнее. Дело в том, $1 не будет интерполировано оболочкой.

Ответ 2

-p switch заставляет Perl перебирать каждую строку ввода и выполнять заданный код для каждого из них (и напечатайте строки после этого). В частности, команда

perl -p -e 'SOME_CODE_HERE;'

в точности эквивалентен запуску следующей программы Perl:

LINE: while (<>) {
    SOME_CODE_HERE;
} continue {
    print or die "-p destination: $!\n";
}

Ваше регулярное выражение, похоже, предназначено для одновременного совпадения нескольких строк, что, очевидно, не будет работать, если Perl обрабатывает входные строки за строкой. Чтобы он работал по назначению, у вас есть (по крайней мере) два варианта:

  • Измените Perl-представление того, что представляет собой строку, используя переключатель -0NNN. В частности, коммутатор -0777 заставляет Perl обрабатывать каждый входной файл как одну "строку".

  • Перепишите код, например. используйте .. оператор flip-flop.

Кстати, я сильно подозреваю, что ваше регулярное выражение не означает, что вы думаете, что это значит. В частности, [^\^]+ соответствует строке одного или нескольких символов, которая не содержит каретки (^). Поскольку ваш ввод, похоже, не содержит никаких кареток, это, по-видимому, эквивалентно (?s:.+) (или просто .+, если вы используете /s модификатор).