用两个空行替换两个以上的连续空行

时间:2017-02-14 09:37:55

标签: bash sed

我正在使用bash,并希望使用单行直接在文件中应用更改,因此sed将是完美的。

我尝试使用sed选项N然后搜索“\ n {3,}”并将其替换为“\ n \ n”,但这不起作用...

sed -ri 'N;N;N;N;s/^(\n){3,}$/\n\n/' ./file

此外,这不会考虑所有搜索模式的出现,因为它必须要求自己起作用。

4 个答案:

答案 0 :(得分:1)

经过一些实验,我想出了以下内容:

/./n      # non-empty line; just print it as normal
N         # otherwise, append the next line
/^\n$/D   # and if it's also empty, delete the first line, and don't print yet

我正在使用GNU sed,当你最后使用N时它不会退出;对于其他实现,您可能需要$!N

您可以通过在最终命令中添加更多\n个字符来轻松调整允许的最大空行数。

这是一个测试,显示它在文件的开头,中间和结尾处起作用:

$ echo $'\n\nabc\n\ndef\n\n\n\n\nabc\n\n\n' | sed -e '/./n;N;/^\n$/D'

abc

def

abc

$

答案 1 :(得分:0)

我不确定这正是您所寻找的,但如果没有,它应该指向正确的方向:

sed -n '/./!H;/./{x;s/\n\{3,\}//p;x;p}'

如果该行为空,请将其放入保留空间。如果该行不为空,则交换模式并保留空间,删除不需要的换行符并打印前一个保留空间。然后从保留空间中取出非空行并打印出来。

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed '/^$/n;//!b;:a;N;s/\n$//;ta' file

如果当前行为空,则打印它并使用下一行刷新。如果当前行不为空,请将其打印并重新开始。如果当前行为空,则删除任何其他空行,直到非空行或文件结尾。

答案 3 :(得分:-1)

根据您的要求,Sed很难保持兼容。但是,既然你只想要一个内衬,那么perl就可以完成这项工作并且可能更便携

如果您需要两个空白行(文本之间有3个换行符):

perl -p0777i -e 's/^\n{3,}/\n\n/; s/\n{4,}/\n\n\n/sg;'  yourfile.txt

如果您需要一个空白行(文本之间有2个换行符):

perl -p0777i -e 's/^\n{2,}/\n/; s/\n{3,}/\n\n/sg;'  yourfile.txt

如果您需要一个空白行,但文件开头没有换行符:

perl -p0777i -e 's/^\n+//; s/\n{3,}/\n\n/sg;'  yourfile.txt

如果你不特别关心文件开头是否有一两个空白:

perl -p0777i -e 's/\n{3,}/\n\n/sg;'  yourfile.txt

测试脚本:

#!/bin/bash 

test_contents()
{
  cat <<EOF



3 blank lines 3 linefeeds prior,  expect 1 removed
3 blank lines 4 linefeeds  after, expect 1 removed



1 blank line, 2 linefeeds after, expect no change

2 blank line, 3 linefeeds after, expect no change


5 blank lines, 6 linefeeds after, expect 3 removed





3 lines to end of file, expect 1 removed



EOF
}

before=$(mktemp -t test_before.XXXXXX)
after=$(mktemp -t test_after.XXXXXX)
sed_after=$(mktemp -t test_sed.XXXXXX)

test_contents > "${before}"
test_contents > "${after}"
test_contents > "${sed_after}"


perl -p0777i -e 's/^\n{3,}/\n\n/; s/\n{4,}/\n\n\n/sg;' "${after}"

echo Orig:
cat "${before}"
echo "Diff:"
diff -U1000 "${before}" "${after}"

这是做什么的:

   -p0777      read whole files in one go
   -i          edit files specified on commandline
   -e          specify the edit expression 

表达式参数/ sg
的意思是:

  s - treat as a whole string including newlines
  g - keep applying the edits until no more can be done

输出是:

+ diff -U1000 /tmp/test_before.XSRHYr /tmp/test_after.mU4hLU
--- /tmp/test_before.XSRHYr 2017-02-14 21:31:09.376110847 +1030
+++ /tmp/test_after.mU4hLU  2017-02-14 21:31:09.379110855 +1030
@@ -1,23 +1,17 @@


-
 3 blank lines 3 linefeeds prior,  expect 1 removed
 3 blank lines 4 linefeeds  after, expect 1 removed


-
 1 blank line, 2 linefeeds after, expect no change

 2 blank line, 3 linefeeds after, expect no change


 5 blank lines, 6 linefeeds after, expect 3 removed


-
-
-
 3 lines to end of file, expect 1 removed


-