Perl match newline in `-0` mode

萝らか妹 提交于 2019-12-11 07:48:29

问题


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).


回答1:


Following should work for you:

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



回答2:


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.




回答3:


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 }'


来源:https://stackoverflow.com/questions/9147438/perl-match-newline-in-0-mode

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!