Perl командной строки многострочной замены - PullRequest
16 голосов
/ 12 марта 2012

Я пытаюсь заменить текст в многострочном файле с помощью командной строки 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 в командной строке.

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

Заранее спасибо.

Ответы [ 2 ]

27 голосов
/ 12 марта 2012

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

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

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

5 голосов
/ 12 марта 2012

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

perl -p -e 'SOME_CODE_HERE;'

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

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

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

  1. Измените представление Perl о том, что представляет собой линия, с помощью переключателя -0<i>NNN</i> .В частности, переключатель -0777 заставляет Perl обрабатывать каждый входной файл как одну «строку».

  2. Переписать свой код, например, с использованием триггера ..оператор .

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...