divide uma linha em muitas partes da base na chave?

0

Eu tenho um arquivo de 1 linha que tem um formato de:

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

Eu quero dividir esta linha e cat para a base de arquivo de saída na chave {} assim. Como eu faço isso?

port1 dev1 M1 s
port1 dev1 M1 s 
port3 dev2 M1 g 
port1 dev1 M1 d 
port1 dev1 M3 g
    
por Trong Nhan Nguyen 11.06.2018 / 13:24

9 respostas

3

Com 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

Ou usando sed:

sed 's/{\([^}]*\)} */\n/; P;D' file
port1 dev1 M1 s
port1 dev1 M1 s
port3 dev2 M1 g
port1 dev1 M1 d
port1 dev1 M3 g
...
    
por 11.06.2018 / 13:38
2

Com o GNU grep construído com suporte a PCRE:

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

Ou para as sequências de não {} incluindo pelo menos um não-espaço:

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

com pcregrep :

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

Se {...} s pode ser aninhado (mas balanceado):

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

Em uma entrada como:

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

Dá:

port1 {dev1 dev2} M1 s
port1 dev1 M1 s
    
por 11.06.2018 / 14:40
1
$ 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

Isso primeiro substitui cada } por uma nova linha usando tr . Isso dá ao comando sed linhas individuais para trabalhar, onde cada linha começará com um espaço possível e um { . Esses caracteres são removidos do início da linha pelo comando sed .

A mesma coisa com apenas sed :

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

O comando y funciona como tr neste exemplo.

Usando o GNU awk ou mawk , mas não o 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

Isso interpreta os dados como registros separados por { ou } e, em seguida, imprime cada registro que contém algo diferente de guias ou espaços.

Usando o 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

Isso aplica um comando print a cada elemento retornado pela correspondência da expressão regular dada com a entrada. O comando print também acrescenta uma nova linha a cada elemento para obtê-los em linhas individuais.

    
por 11.06.2018 / 14:09
0

Solução com sed + tr .

sed -e '1,$s/}\s/#/g' input-file | tr '#' '\n' | tr -d '{|}' > output-file
    
por 11.06.2018 / 13:44
0

Uma solução com o GNU sed:

sed -e 's/} {/\n/g' -e 's/^{//' -e 's/}//' input-file > output-file
    
por 11.06.2018 / 13:37
0

Usando o grep + tr:

grep -o  "{[^}]*" file | tr -d '{'

Usando sed:

sed -e 's/{\(.*\)}//' -e 's/} {/\n/g' file
    
por 11.06.2018 / 14:09
0

Isso pode ser feito usando "sed" como mostrado:

sed -ne 'y/{}/\n\n/;/^\s/D;/./P;D' input.file

onde o combo P; D configura um loop implícito e durante o corpo do loop nós nos asseguramos de imprimir campos não vazios.

Ao longo de linhas semelhantes:

perl -lne 'print for grep /\H/, split /{|}/' input.file

onde dividimos o registro, filtramos os campos não vazios e os imprimimos um / linha em um loop for.

    
por 11.06.2018 / 15:57
0

Com bash

var=$(<infile)
var="${var//\} {/$'\n'}"
echo "${var//[{\}]}"
    
por 11.06.2018 / 18:09
0

com tr :

<infile tr -s '}{' '\n '
 port1 dev1 M1 s
 port1 dev1 M1 s
 port3 dev2 M1 g
 port1 dev1 M1 d
 port1 dev1 M3 g
    
por 11.06.2018 / 19:17