基于花括号将一行分成许多部分?

基于花括号将一行分成许多部分?

我有一个 1 行文件,其格式为:

{port1 dev1 M1 s} {port1 dev1 M1 s} {port3 dev2 M1 g} {port1 dev1 M1 d} {port1 dev1 M3 g} ...

我想将这一行和 cat 分割为基于大括号 { } 的输出文件,如下所示。我怎么做 ?

port1 dev1 M1 s
port1 dev1 M1 s 
port3 dev2 M1 g 
port1 dev1 M1 d 
port1 dev1 M3 g

答案1

使用 Perl:

perl -lne 'print for /{(.*?)}/g' file
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g

或者使用 sed:

sed 's/{\([^}]*\)} */\1\n/; P;D' file
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g
...

答案2

grep使用带有 PCRE 支持的GNU :

grep -Po '{\K[^}]*'

或者对于至少包含非空格的非 {} 序列:

grep -o '[^{}]*[^{}[:space:]][^{}]*'

pcregrep

pcregrep -o1 '{(.*?)}'

如果{...}s 可以嵌套(但平衡):

pcregrep -o1 '{((?:[^{}]+|(?0))*)}'

在这样的输入上:

{port1 {dev1 dev2} M1 s} {port1 dev1 M1 s}

它给:

port1 {dev1 dev2} M1 s
port1 dev1 M1 s

答案3

$ tr '}' '\n' <file | sed -E 's/^ ?\{//'
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g

首先}使用 替换每个换行符tr。这为sed命令提供了单独的行来处理,其中每行将以可能的空格和 开头{。这些字符将被命令从行首删除sed

同样的事情只是sed

sed -E -e 's/ ?\{//g' -e 'y/}/\n/'

该命令的工作方式与本示例y类似。tr


使用 GNUawkmawk,但不使用 BSD awk

$ awk -v RS='[{}]' '/[^[:blank:]]/' file
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g

这会将数据解释为由 或 分隔的记录{}然后打印每个包含制表符或空格以外的内容的记录。


使用 Perl:

$ perl -ne 'map { print "$_\n" } /{(.*?)}/g' file
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g

这会将print命令应用于通过将给定正则表达式与输入进行匹配而返回的每个元素。该print命令还会向每个元素附加一个换行符,以使它们位于单独的行上。

答案4

GNU sed 的解决方案:

sed -e 's/} {/\n/g' -e 's/^{//' -e 's/}//' input-file > output-file

相关内容