简体   繁体   中英

Perl match newline in `-0` mode

Question

Suppose I have a file like this:

I've got a loverly bunch of coconut trees.

Newlines!

Bahahaha
Newlines!
the end.

I'd like to replace an occurence of "Newlines!" that is surrounded by blank lines with (say) NEWLINES!. So, ideal output is:

I've got a loverly bunch of coconut trees.

NEWLINES!

Bahahaha
Newlines!
the end.

Attempts

Ignoring "surrounded by newlines", I can do:

perl -p -e 's@Newlines!@NEWLINES!@g' input.txt

Which replaces all occurences of "Newlines!" with "NEWLINES!".

Now I try to pick out only the "Newlines!" surrounded with \\n:

perl -p -e 's@\nNewlines!\n@\nNEWLINES!\n@g' input.txt

No luck (note - I don't need the s switch because I'm not using . and I don't need the m switch because I'm not using ^ and $ ; regardless, adding them doesn't make this work). Lookaheads/behinds don't work either:

perl -p -e 's@(?<=\n)Newlines!(?=\n)@NEWLINES!@g' input.txt

After a bit of searching, I see that perl reads in the file line-by-line (makes sense; sed does too). So, I use the -0 switch:

perl -0p -e 's@(?<=\n)Newlines!(?=\n)@NEWLINES!@g' input.txt

Of course this doesn't work -- -0 replaces new line characters with the null character.

So my question is -- how can I match this pattern (I'd prefer not to write any perl beyond the regex 's@pattern@replacement@flags' construct)?

Is it possible to match this null character? I did try:

perl -0p -e 's@(?<=\0)Newlines!(?=\0)@NEWLINES!@g' input.txt

to no effect.

Can anyone tell me how to match newlines in perl? Whether in -0 mode or not? Or should I use something like awk ? (I started with sed but it doesn't seem to have lookahead/behind support even with -r . I went to perl because I'm not at all familiar with awk).

cheers.

(PS: this question is not what I'm after because their problem had to do with a .+ matching newline).

以下应该为您工作:

perl -0pe 's@(?<=\n\n)Newlines!(?=\n\n)@NEWLINES!@g'

If the file is small enough to be slurped into memory all at once:

perl -0777 -pe 's/\n\nNewlines!(?=\n\n)/\n\nNEWLINES!/g'

Otherwise, keep a buffer of the last three lines read:

perl -ne 'push @buffer, $_; $buffer[1] = "NEWLINES!\n" if @buffer == 3 && ' \
      -e 'join("", @buffer) eq "\nNewlines!\n\n"; ' \
      -e 'print shift @buffer if @buffer == 3; END { print @buffer }'

I think they way you went about things caused you to combine possible solutions in a way that didn't work.

if you use the inline editing flag you can do it like this:

perl -0p -i.bk -e 's/\n\nNewlines!\n\n/\n\nNEWLINES!\n\n/g' input.txt

I have doubled the \\n's to make sure you only get the ones with empty lines above and below.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM