如何替换括号之间的换行符
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
能力将其设置为空。然后使用 awk
的 match
函数匹配 seq-cont {
之间的所有内容,直到下一次出现 }
。删除所有空格,匹配值中的新行。最后打印所有值,包括新编辑的值,以获得 OP 提到的预期输出。
我有类似这种格式的日志文件
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
能力将其设置为空。然后使用 awk
的 match
函数匹配 seq-cont {
之间的所有内容,直到下一次出现 }
。删除所有空格,匹配值中的新行。最后打印所有值,包括新编辑的值,以获得 OP 提到的预期输出。