Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl command line multi-line replace

I'm trying to replace text in a multi-line file using command-line perl. I'm using Ubuntu Natty.

Below is the content of my text file (called 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

Below is my perl command:

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

However, instead of replacing all the text in the file, below is what I end up with:

[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
#

I tried the Regex in RegexBuddy for Perl and it matches everything in the text file, but for some reason it's not working using perl on the command line.

I'd appreciate some assistance.

Thanks in advance.

like image 636
ObiHill Avatar asked Mar 12 '12 15:03

ObiHill


People also ask

How do I match multiple lines in Perl?

Solution. Use /m , /s , or both as pattern modifiers. /s lets . match newline (normally it doesn't). If the string had more than one line in it, then /foo.

What does Perl 0777 do?

And 0777 will force Perl to read the whole file in one shot because 0777 is not a legal character value. -- This option must be used in conjunction with either the -n or -p option. Using the -a option will automatically feed input lines to the split function. The results of the split are placed into the @F variable.

How do I search and replace in Perl?

Performing a regex search-and-replace is just as easy: $string =~ s/regex/replacement/g; I added a “g” after the last forward slash. The “g” stands for “global”, which tells Perl to replace all matches, and not just the first one.


1 Answers

You are reading the file line-by-line, so only the first line matches your regex. What you'll want to do -- if you truly wish to delete most of the content -- is to slurp the file by using the -0 option, e.g. -0777. This is line ending processing, and 777 is just a number used by convention as an octal number large enough so as to cause file slurping.

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

Also, I replaced your quotes. If you are in *nix, which it seems you are, single quotes are preferable. Case in point, $1 would not be interpolated by the shell.

like image 111
TLP Avatar answered Oct 09 '22 07:10

TLP