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
How to Install Svn Post-Commit Hook
Responsibility of Stack Alignment in 32-Bit X86 Assembly
How to Pass Argument with Exclamation Mark on Linux
How to Force Abort on "Glibc Detected *** Free(): Invalid Pointer"
Openshift: "Failed to Execute Control Start" on Node Application
Hardware Cache Events and Perf
Will Read() Ever Block After Select()
How to Get Amount of Queued Data for Udp Socket
Receiving Key Press and Key Release Events in Linux Terminal Applications
How to Reference Files Relative to Application Root in Node.Js
X86_64 Assembly Linux System Call Confusion
Joining Multiple Fields in Text Files on Unix
Bluetooth Le Signal Strength Linux