在 shell 命令行中将两个换行符替换为一个

发布于 12-06 09:08 字数 691 浏览 0 评论 0原文

关于将多个换行符替换为一个换行符存在很多问题,但没有人为我工作。
我有一个文件:

first line
second line MARKER

third line MARKER
other lines

many other lines

我需要将 MARKER 之后的两个换行符(如果存在)替换为一个换行符。结果文件应该是:

first line
second line MARKER
third line MARKER
other lines

many other lines

我尝试 sed ':a;N;$!ba;s/MARKER\n\n/MARKER\n/g' 失败。
sed 对于单行替换很有用,但对于换行符有问题。它找不到\n\n

我尝试了perl -i -p -e 's/MARKER\n\n/MARKER\n/g'失败。< br> 这个解决方案看起来更接近,但似乎正则表达式没有对 \n\n 做出反应。

是否可以只替换MARKER之后的\n\n而不替换文件中的其他\n\n
我对单行解决方案感兴趣,而不是脚本。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

孤独患者2024-12-13 09:08:03

我认为你走在正确的道路上。在多行程序中,您可以将整个文件加载到单个标量中并对其运行此替换:

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

让单行程序将文件加载到多行字符串中的技巧是设置 $/BEGIN 块中。该代码将在读取输入之前执行一次。

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

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
因为看清所以看轻2024-12-13 09:08:03

您的 Perl 解决方案不起作用,因为您正在搜索包含两个换行符的行。没有这样的事情。这是一种解决方案:

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

Or in-place:

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

如果您同意将整个文件加载到内存中,您可以使用

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

or

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

如上所述,您可以使用 -i~ 进行就地编辑。如果您不想进行备份,请删除 ~

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.

陌上青苔2024-12-13 09:08:03

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

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
孤独陪着我2024-12-13 09:08:03
awk '
  marker { marker = 0; if (/^$/) next }
  /MARKER/ { marker = 1 }
  { print }
'
awk '
  marker { marker = 0; if (/^$/) next }
  /MARKER/ { marker = 1 }
  { print }
'
凹づ凸ル2024-12-13 09:08:03

这可以通过非常简单的 sed 来完成。

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

This can be done in very simple sed.

sed '/MARKER$/{n;/./!d}'
帝王念2024-12-13 09:08:03

这可能对您有用:

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

说明:

删除 MARKER 之间的所有行,保留 MARKER 行。

或者:

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

说明:

读取 MARKER 之后的下一行,然后追加该行。如果当前行是 MARKER 行,则删除上一行。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文