replace two newlines to one in shell command line

自闭症网瘾萝莉.ら 提交于 2019-12-10 10:43:51

问题


There are lot of questions about replacing multi-newlines to one newline but no one is working for me.
I have a file:

first line
second line MARKER

third line MARKER
other lines

many other lines

I need to replace two newlines (if they exist) after MARKER to one newline. A result file should be:

first line
second line MARKER
third line MARKER
other lines

many other lines

I tried sed ':a;N;$!ba;s/MARKER\n\n/MARKER\n/g' Fail.
sed is useful for single line replacements but has problems with newlines. It can't find \n\n

I tried perl -i -p -e 's/MARKER\n\n/MARKER\n/g' Fail.
This solution looks closer, but it seems that regexp didn't reacts to \n\n.

Is it possible to replace \n\n only after MARKER and not to replace other \n\n in the file?
I am interested in one-line-solution, not scripts.


回答1:


I think you were on the right track. In a multi-line program, you would load the entire file into a single scalar and run this substitution on it:

s/MARKER\n\n/MARKER\n/g

The trick to getting a one-liner to load a file into a multi-line string is to set $/ in a BEGIN block. This code will get executed once, before the input is read.

perl -i -pe 'BEGIN{$/=undef} s/MARKER\n\n/MARKER\n/g' input



回答2:


Your Perl solution doesn't work because you are search for lines that contain two newlines. There is no such thing. Here's one solution:

perl -ne'print if !$m || !/^$/; $m = /MARKER$/;' infile > outfile

Or in-place:

perl -i~ -ne'print if !$m || !/^$/; $m = /MARKER$/;' file

If you're ok with loading the entire file into memory, you can use

perl -0777pe's/MARKER\n\n/MARKER\n/g;' infile > outfile

or

perl -0777pe's/MARKER\n\K\n//g;' infile > outfile

As above, you can use -i~ do edit in-place. Remove the ~ if you don't want to make a backup.




回答3:


awk:

kent$  cat a
first line
second line MARKER

third line MARKER
other lines

many other lines

kent$  awk 'BEGIN{RS="\x034"} {gsub(/MARKER\n\n/,"MARKER\n");printf $0}' a
first line
second line MARKER
third line MARKER
other lines

many other lines



回答4:


See sed one liners.




回答5:


awk '
  marker { marker = 0; if (/^$/) next }
  /MARKER/ { marker = 1 }
  { print }
'



回答6:


This can be done in very simple sed.

sed '/MARKER$/{n;/./!d}'



回答7:


This might work for you:

 sed '/MARKER/,//{//!d}'

Explanation:

Deletes all lines between MARKER's preserving the MARKER lines.

Or:

sed '/MARKER/{n;N;//D}'

Explanation:

Read the next line after MARKER, then append the line after that. Delete the previous line if the current line is a MARKER line.



来源:https://stackoverflow.com/questions/7535587/replace-two-newlines-to-one-in-shell-command-line

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