Perl Command Line Multi-Line Replace

Multiline search replace with Perl

This kind of search and replace can be accomplished with a one-liner such as -

perl -i -pe 's/START.*STOP/replace_string/g' file_to_change

For more ways to accomplish the same thing check out this thread. To handle multi-line searches use the following command -

perl -i -pe 'BEGIN{undef $/;} s/START.*STOP/replace_string/smg' file_to_change

In order to convert the following code from a one-liner to a perl program have a look at the perlrun documentation.

If you really find the need to convert this into a working program then just let Perl handle the file opening/closing for you.

#!/usr/bin/perl -pi
#multi-line in place substitute - subs.pl
use strict;
use warnings;

BEGIN {undef $/;}

s/START.*STOP/replace_string/smg;

You can then call the script with the filename as the first argument

$perl subs.pl file_to_change

If you want a more meatier script where you get to handle the file open/close operations(don't we love all those 'die' statements) then have a look at the example in perlrun under the -i[extension] switch.

Perl command line multi-line replace

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.

Perl command line to replace text block across multi-line using regex

You can set the record separator with the -0 option. Like so:

perl -0pe 's/.../.../g' *.html

This sets the record separator to the NUL character, so that the entire file is read at once, rather than line by line.

perl Multiline Find and Replace with regex

One way is to slurp the entire file, from perlrun doc

The special value 00 will cause Perl to slurp files in paragraph mode.
Any value 0400 or above will cause Perl to slurp files whole, but by
convention the value 0777 is the one normally used for this purpose.

I have slightly modified sample input for demonstration:

$ cat ip.txt 
#DEV
#jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
#ems_value=emsdev.example
xyz #DEV
#abc

Adding -0777 option to OP's regex

$ perl -0777 -pe 's/#DEV\n#(.*)/#DEV\n\1/g' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
abc

If #DEV has to be matched at start of line only, use m flag

$ perl -0777 -pe 's/^#DEV\n#(.*)/#DEV\n\1/mg' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
#abc



Positive lookbehind can be used as well:

$ perl -0777 -pe 's/^#DEV\n\K#//mg' ip.txt 
#DEV
jms_value=devdata.example
#TST
#jms_value=tstdata.example
#DEV
ems_value=emsdev.example
xyz #DEV
#abc



Also note: What is the difference between \1 and $1 in a Perl regex?

perl command line multiline regex substitute

perl -pe does line by line processing. So using a regex that spans lines is never going to match by default.

You can change the input record separator $/ though, to slurp the entire file and apply the regex to it:

perl -pe "BEGIN { undef $/ } s/^@.*\n\s*\n+//mg" test.txt

The regex you suggested above doesn't provide the output you want though. To do that, you'd need the following expression:

perl -pe "BEGIN {undef $/} s/^@.*\n\s*\n(?:(?!\@).*\n)*//mg" text.txt

Outputs:

@LNCaP.2622 GAPC:1:1:4519:1350 length=76
TTTCCATTGCAGGTTTTAAAGTGGAGATTCTGAAGGGGAAAATAGGCACTGTCAGAACAAAGCTACCTGGAAACAG
+LNCaP.2622 GAPC:1:1:4519:1350 length=76
DD@:BBBBDDD@D:B::=:6:(6//;589444004':839>>2;;:':>>:7B:><B<B#################
@LNCaP.2624 GAPC:1:1:4794:1349 length=76

How do I search and replace across multiple lines with Perl?

You can use the -0 switch to change the input separator:

perl -0777pe 's/foo\nbar/FOO\nBAR/' baz.txt

-0777 sets the separator to undef, -0 alone sets it to \0 which might work for text files not containing the null byte.

Note that /m is needless as the regex does not contain ^ nor $.

Replace a multiline pattern using Perl, sed, awk

Note that a better way to combine multiple JSON files is to parse them all, combine the parsed data structure, and reencode the result. Simply changing all occurrences of ][ to a comma , may alter data instead of markup

sed is a minimal program that will operate only on a single line of a file at a time. Perl encompasses everything that sed or awk will do and a huge amount more besides, so I suggest you stick with it

To change all ]...[ pairs in file.json (possibly separated by whitespace) to a single comma, use this

perl -0777 -pe "s/\]\s*\[/,/g" file.json > file2.json

The -0 option specifies an octal line separator, and giving it the value 777 makes perl read the entire file at once

One-liners are famously unintelligible, and I always prefer a proper program file, which would look like this

join_brackets.pl

use strict;
use warnings 'all';

my $data = do {
local $/;
<>;
}

$data =~ s/ \] \s* \[ /,/gx;

print $data;

and you would run it as

perl join_brackets.pl file.json > joined.json


Related Topics



Leave a reply



Submit