2012-03-12 5 views
14

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

Ниже содержание моего текстового файла (так называемый 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 в командной строке.

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

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

+5

Я не уверен, каким должен быть ожидаемый результат. – cornuz

+0

@cornuz Я думаю, что это видно из вопроса. Я сказал: «Вместо того, чтобы заменить весь текст в файле, [следующее] - это то, в чем я заканчиваю ...», так что это в значительной степени объясняет это. Кроме того, из регулярного выражения я считаю, что кажется довольно ясным, какой результат мне нужен. –

ответ

24

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

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

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

+0

Большое вам спасибо. Мне пришлось изменить его на это: 'perl -0777 -i -pe 's/(\ [mysqld \] [^ \ ^] +)/\ 1 \ nsometext/g" test.txt', потому что я собираюсь необходимо использовать некоторые переменные оболочки позже. Приветствия. –

+0

@ChuckUgwuh Рад помочь. – TLP

+0

Cheers. Вы знаете, как включить переменные оболочки с помощью одиночных кавычек ?! В двойных кавычках я делаю что-то вроде этого: 'perl -0777 -i -pe 's/(\ [mysqld \] [^ \ ^] +)/\ 1 \ n $ var/g" test.txt', it было бы хорошо знать, как я могу добиться того же самого, используя одиночные кавычки ?! Еще раз спасибо. –

5

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

perl -p -e 'SOME_CODE_HERE;' 

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

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

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

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

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

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

+0

Спасибо. Я не совсем разбираюсь в командной строке, как подсказывает ваш ответ, но я нахожу это достаточно информативным. ура –