我有一个 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
使用 GNUawk
或mawk
,但不使用 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