Bash 在mac上匹配sed中的重复字符

Bash 在mac上匹配sed中的重复字符,bash,sed,bsd,Bash,Sed,Bsd,我试图找到3行或更多新行的所有实例,并用2行新行替换它们(想象一个文件有太多的空白)。我正在使用sed,但是如果更容易的话,可以使用awk或类似的方法来回答 注意:我在mac电脑上,因此sed与linux上略有不同(BSD与GNU) 我的实际目标是新行,但我根本无法让它工作,因此为了简单起见,我尝试匹配3次或更多重复的bla,并将其替换为bla 制作一个名为dumby.txt的示例文件: $ cat stupid.txt blablabla $ 我的理解是,您可以使用正则表达式语法thing

我试图找到3行或更多新行的所有实例,并用2行新行替换它们(想象一个文件有太多的空白)。我正在使用sed,但是如果更容易的话,可以使用awk或类似的方法来回答

注意:我在mac电脑上,因此sed与linux上略有不同(BSD与GNU)

我的实际目标是新行,但我根本无法让它工作,因此为了简单起见,我尝试匹配3次或更多重复的
bla
,并将其替换为
bla

制作一个名为dumby.txt的示例文件:

$ cat stupid.txt

blablabla
$
我的理解是,您可以使用正则表达式语法
thing{i,}

我尝试过这一版本,以匹配3
bla
s,但运气不佳:

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

现在我想不出还有什么可以尝试的了

thing{3,}
匹配
thinggg
。使用
(…)
对事物进行分组,使量词适用于您想要的:

$ echo blablabla | sed -E 's/(bla){3}/BLA/g'
BLA

thing{3,}
匹配
thinggg
。使用
(…)
对事物进行分组,使量词适用于您想要的:

$ echo blablabla | sed -E 's/(bla){3}/BLA/g'
BLA
以上匹配
bl
,然后重复三次或更多次
a
。这不是你想要的。看起来您实际上想要重复三次或更多的
bla
。如果是这种情况,则更换:

$ sed -E 's/bla{3,}/BLA/g' stupid.txt
blablabla
与:

不过,上述内容并不能直接帮助您完成替换换行符的任务,因为默认情况下,
sed
一次只能读取一行

替换换行符

让我们考虑这个文件,它在<代码> 1 < /代码>和<代码> 2 > /代码>:< /P>之间有3个换行符。

$ cat file.txt

1



3
要用一个换行符替换出现的三个或多个换行符,请执行以下操作:

$ sed -E 'H;1h;$!d;x; s/\n{3,}/\n/g' file.txt

1
3
工作原理:

  • H;1h;$!Dx

    这一系列复杂的命令读取整个文件。可能是的 这是一个最简单的成语。如果你真的想知道 血淋淋的细节:

    • H
      -追加当前行以保留空格
    • 1h
      -如果这是第一行,覆盖保留空间 用它
    • $!d
      -如果这不是最后一行,请删除图案空间 然后跳到下一行
    • x
      -交换保留空间和模式空间以放入整个文件 模式空间
  • s/\n{3,}/\n/g

    这将用一个换行符替换三个或更多换行符的所有序列

候补 上述解决方案一次读取整个文件。对于大型(GB)文件,这可能是一个缺点。这种替代方法避免了以下情况:

$ 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
以上匹配
bl
,然后重复三次或更多次
a
。这不是你想要的。看起来您实际上想要重复三次或更多的
bla
。如果是这种情况,则更换:

$ sed -E 's/bla{3,}/BLA/g' stupid.txt
blablabla
与:

不过,上述内容并不能直接帮助您完成替换换行符的任务,因为默认情况下,
sed
一次只能读取一行

替换换行符

让我们考虑这个文件,它在<代码> 1 < /代码>和<代码> 2 > /代码>:< /P>之间有3个换行符。

$ cat file.txt

1



3
要用一个换行符替换出现的三个或多个换行符,请执行以下操作:

$ sed -E 'H;1h;$!d;x; s/\n{3,}/\n/g' file.txt

1
3
工作原理:

  • H;1h;$!Dx

    这一系列复杂的命令读取整个文件。可能是的 这是一个最简单的成语。如果你真的想知道 血淋淋的细节:

    • H
      -追加当前行以保留空格
    • 1h
      -如果这是第一行,覆盖保留空间 用它
    • $!d
      -如果这不是最后一行,请删除图案空间 然后跳到下一行
    • x
      -交换保留空间和模式空间以放入整个文件 模式空间
  • s/\n{3,}/\n/g

    这将用一个换行符替换三个或更多换行符的所有序列

候补 上述解决方案一次读取整个文件。对于大型(GB)文件,这可能是一个缺点。这种替代方法避免了以下情况:

$ 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

如果可以对整个文件进行slurping:

perl -0777pe 's/(\n){3,}/\n\n/g' newlines.txt
perl -ne 'if (/^$/) {$i++}else{$i=0}print if $i<3' newlines.txt
您应该用合适的换行顺序替换
\n

-0777
告诉perl不要将每一行打断为自己的记录,这允许跨行工作的正则表达式运行

如果你有