如何替换括号之间的换行符

How to replace newlines between brackets

我有类似这种格式的日志文件

test {
seq-cont {
                        0,
                        67,
                        266
                        },
                grp-id 505
        }
}
test{
        test1{
                val
        }
}

这是产生该输出的 echo 命令

$ echo -e "test {\nseq-cont {\n\t\t\t0,\n\t\t\t67,\n\t\t\t266\n\t\t\t},\n\t\tgrp-id 505\n\t}\n}\ntest{\n\ttest1{\n\t\tval\n\t}\n}\n"

问题是如何删除文件中 seq-cont { 和下一个 } 之间的所有空格。

我希望输出是这样的。最好使用 sed 来生成输出。

test{seq-cont{0,67,266},
                       grp-id 505
        }
}
test{
        test1{
                val
        }
}

OP 的努力:这是一个有点奏效但不完全是我想要的:

sed ':a;N;/{/s/[[:space:]]\+//;/}/s/}/}/;ta;P;D' logfile

您可以使用 perl 更轻松地做到这一点:

perl -0777 -i -pe 's/\s+(seq-cont\s*\{[^}]*\})/=~s|\s+||gr/ge' logfilepath

-0777 选项告诉 perl 将文件压缩成单个字符串,-i 保存内联更改,\s+(seq-cont\s*\{[^}]*\}) 正则表达式匹配一个或多个空格,然后捕获到第 1 组 (</code>) <code>seq-cont,零个或多个空格,然后是最左边的 { 和下一个 } 字符之间的子字符串([^}]* 匹配零或 } 以外的多个字符),然后从整个第 1 组值 (</code>) 中删除所有一个或多个空白字符块(与 <code>\s+ 匹配)(第二个内部替换是使用 e 标志启用)。由于 g 标志(在 e 旁边),所有事件都得到处理。

参见 online demo:

#!/bin/bash
s=$(echo -e "test {\nseq-cont {\n\t\t\t0,\n\t\t\t67,\n\t\t\t266\n\t\t\t},\n\t\tgrp-id 505\n\t}\n}\ntest{\n\ttest1{\n\t\tval\n\t}\n}\n")
perl -0777 -pe 's/\s+(seq-cont\s*\{[^}]*\})/=~s|\s+||gr/ge' <<< "$s"

输出:

test {seq-cont{0,67,266},
        grp-id 505
    }
}
test{
    test1{
        val
    }
}

可以使用 gnu-awk 和匹配 { 的自定义 RS 正则表达式并关闭 }:

来完成
awk -v RS='{[^}]+}' 'NR==1 {gsub(/[[:space:]]+/, "", RT)} {ORS=RT} 1' file

test {seq-cont{0,67,266},
                grp-id 505
        }
}
test{
        test1{
                val
        }
}

这里:

  • NR==1 {gsub(/[[:space:]]+/, "", RT)}: 对于第一条记录,将所有空格(包括换行符)替换为空字符串。
  • {ORS=RT}:将 ORS 设置为我们在 RS
  • 中捕获的任何文本

PS:如果要对整个文件执行此操作,请删除 NR==1

使用您显示的示例,请尝试执行以下 awk 程序。在 GNU awk.

中测试和编写
awk -v RS= '
match([=10=],/{\nseq-cont {\n[^}]*/){
  val=substr([=10=],RSTART,RLENGTH)
  gsub(/[[:space:]]+/,"",val)
  print substr([=10=],1,RSTART-1) val substr([=10=],RSTART+RLENGTH)
}
'  Input_file

解释: 简单的解释就是,使用 RS 能力将其设置为空。然后使用 awkmatch 函数匹配 seq-cont { 之间的所有内容,直到下一次出现 }。删除所有空格,匹配值中的新行。最后打印所有值,包括新编辑的值,以获得 OP 提到的预期输出。