我正在尝试查找3个或更多新行的所有实例,并用仅2个新行替换它们(想象一个文件太多白色空间)。我正在使用sed,但如果更容易,可以使用awk或类似的答案。
注意:我在Mac上,所以sed与linux上略有不同(BSD与GNU)
我的实际目标是换行,但我无法让它工作,所以为了简单起见,我试图匹配3次或更多次bla
重复,并将其替换为BLA
。
创建一个名为stupid.txt的示例文件:
$ cat stupid.txt
blablabla
$
我的理解是您使用正则表达式语法thing{i,}
匹配 i或更多内容。
我尝试过这种变体来匹配3 bla
没有运气:
cat stupid.txt | sed 's/bla{3,}/BLA/g' # simplest way
cat stupid.txt | sed 's/bla\{3,\}/BLA/g' # escape curly brackets
cat stupid.txt | sed -E 's/bla{3,}/BLA/g' # use extended regular expressions
cat stupid.txt | sed -E 's/bla\{3,\}/BLA/g' # use -E and escape brackets
现在我没有想过要尝试的其他方法!
答案 0 :(得分:5)
thing{3,}
匹配thinggg
。使用(..)
对事物进行分组,使量词适用于您想要的内容:
$ echo blablabla | sed -E 's/(bla){3}/BLA/g'
BLA
答案 1 :(得分:2)
sed -E 's/bla{3,}/BLA/g'
以上匹配bl
,然后重复三次或更多次a
。这不是你想要的。您似乎确实需要三次或更多次重复bla
。如果是这种情况,则替换:
$ sed -E 's/bla{3,}/BLA/g' stupid.txt
blablabla
使用:
$ sed -E 's/(bla){3,}/BLA/g' stupid.txt
BLA
但是,上述内容并没有直接帮助您更换新行,因为默认情况下,sed
一次只能读取一行。
让我们考虑一下这个文件在1
和2
之间有3个换行符:
$ cat file.txt
1
3
用一个换行替换任何三个或更多换行符:
$ sed -E 'H;1h;$!d;x; s/\n{3,}/\n/g' file.txt
1
3
工作原理:
H;1h;$!d;x
这一系列复杂的命令读入整个文件。可能是 最简单的想到这是一个成语。如果你真的想知道 血淋淋的细节:
H
- 附加当前行以容纳空格1h
- 如果这是第一行,则覆盖保留空间
用它$!d
- 如果这不是最后一行,请删除模式空间
然后跳到下一行。x
- 交换保留和模式空间以放入整个文件
模式空间 s/\n{3,}/\n/g
用一个换行符替换三个或更多换行符的所有序列。
上述解决方案立即读入整个文件。对于可能不利的大(千兆字节)文件。这种替代方法避免了:
$ sed -E '/^$/{:a; N; /\n$/ba; s/\n{3,}([^\n]*)/\1/}' file.txt # GNU only
1
3
工作原理:
/^$/{...}
选择空白行。对于空行和仅空白行,将执行大括号中的命令,它们是:
:a
这定义了标签a
。
N
这将从文件的下一行读入模式空间,与换行符分开。
/\n$/ba
如果读入的最后一行为空,则跳转(跳转)到标签a
。
s/\n{3,}([^\n]*)/\1/
如果我们没有分支,则执行此替换以删除多余的换行符。
BSD版:我没有BSD系统来测试这个,但我猜:
sed -E -e '/^$/{:a' -e N -e '/\n$/ba' -e 's/\n{3,}([^\n]*)/\1/}' file.txt
答案 2 :(得分:2)
如果可以接受整个文件:
perl -0777pe 's/(\n){3,}/\n\n/g' newlines.txt
你应该用适当的换行符替换\n
。
-0777
告诉perl不要将每一行分成它自己的记录,这允许跨行工作的正则表达式起作用。
如果您对结果感到满意,-i
会导致perl就地替换文件而不是输出到stdout:
perl -i -0777pe 's/(\n){3,}/\n\n/g' newlines.txt
您也可以这样做:-i~
创建一个具有给定后缀的备份文件(在这种情况下为~
)。
如果不能接受整个文件:
perl -ne 'if (/^$/) {$i++}else{$i=0}print if $i<3' newlines.txt
这将打印不是第三个(或更高)连续空行的任何行。 -i
同样适用。
ps - MacOS随附perl。
答案 3 :(得分:1)
要仅保留2个换行符,您可以尝试使用此sed
sed '
/^$/!b
N
/../b
h
:A
y/\n/@/
/^@$/!bB
s/@//
$bB
N
bA
:B
s/^@//
/./ {
x
G
b
}
g
' infile
/ ^ $ /!b如果它是空行则不打印
N获得一个新行
/../ b如果这个新行不为空,则打印2行
h将2个空行保留在保持缓冲区
中:标签A
此时模式缓冲区总是有2行,第一行是空的
> @ / n / @ /替换\ n由@(您可以选择文件中不存在的其他字符)/ ^ @ $ /!bB如果第二行不为空,则跳转到B
s / @ //删除@
$ bB如果最后一行跳到B
此时模式空间中有1个空行
N得到最后一行
bA跳到A
:B标签B
s / ^ @ //删除行开头的@
/./ {如果最后一行不为空
x交换模式和保持缓冲区
G将保持缓冲区添加到模式空间
b跳到最后
}
用保留空间
替换模式空间(空)打印图案空间