Como transformar o texto de forma que cada linha de saída comece com o título do bloco?

1

Eu preciso fazer um script para transformar o seguinte:

Name = x:y
Z =  a:b.c
Z1 = a1:b1.c1
End
Name=x1:y1
Z2 = a2:b2.c2
Z3 = a3:b3.c3
Z4 = a4:b4.c4
End
Name = l:k
s = w:e.v
End

para:

x:y Z    a:b.c
x:y Z1   a1:b1.c1
x1:y1   Z2   a2:b2.c2
x1:y1   Z3   a3:b3.c3
x1:y1   Z4   a4:b4.c4
l:k s    w:e.v
    
por ahmed 26.08.2013 / 21:07

3 respostas

5

Usando = com espaço em branco opcional como o delimitador:

awk -F '[[:blank:]]*=[[:blank:]]*' '
    $1 == "Name" {name = $2; next}
    $1 != "End"  {print name, $1, $2}
' filename

Exemplo

Ao olhar para essas soluções awk , pode ficar um pouco confuso o que está acontecendo. Se você inserir algumas declarações de impressão bem colocadas, poderá começar a ver de maneira visual o que está acontecendo:

$ awk -F '[[:blank:]]*=[[:blank:]]*' '
      $1 == "Name" { name = $2; print "--NAME: "$2; next }; 
      $1 != "End" { print " --END: "name,$1,$2 }
' sample.txt

Que produz a seguinte saída:

--NAME: x:y
 --END: x:y Z a:b.c
 --END: x:y Z1 a1:b1.c1
--NAME: x1:y1
 --END: x1:y1 Z2 a2:b2.c2
 --END: x1:y1 Z3 a3:b3.c3
 --END: x1:y1 Z4 a4:b4.c4
--NAME: l:k
 --END: l:k s w:e.v
    
por 26.08.2013 / 21:19
1

Uma forma de usar

Este pequeno comando sed pode fazer o trabalho:

sed -ne '
  /^Name */{
    s/^.*= *//;
    h;
    tb;
  };
  /^End/bb;
  G;
  s/^\(.*\) *= *\(.*\)\n\(.*\)$/\t\t/p;
  :b
  ' <sourcefile.txt 
x:y Z       a:b.c
x:y Z1      a1:b1.c1
x1:y1       Z2      a2:b2.c2
x1:y1       Z3      a3:b3.c3
x1:y1       Z4      a4:b4.c4
l:k s       w:e.v

Explicado:

  • Se uma linha começar por Nome , solte até = , em vez de armazená-las em hold space e pule para o rótulo :b .
  • Se uma linha começar por Fim , pule a próxima etapa até o rótulo :b .
  • Antes do marcador :b (se mais): Adicione hold space , do que se a sequência de correspondência de linhas ', seguida por qualquer número de espaços e um sinal de igual, alguns espaços talvez, um segundo string, newline e finalmente uma terceira string, then imprime terceira string, seguida por uma tab, primeiro string uma tabulação e depois a segunda string.

E uma forma de usar apenas

while read line ;do
    if [ ${line//=*} = "Name" ] ;then
        name=${line//*=}
    else
        [ "${line//=*}" != "$line" ] &&
            printf "%s\t%s\t%s\n" $name ${line//=}
    fi
  done <sourcefile.txt 
x:y Z       a:b.c
x:y Z1      a1:b1.c1
x1:y1       Z2      a2:b2.c2
x1:y1       Z3      a3:b3.c3
x1:y1       Z4      a4:b4.c4
l:k s       w:e.v
    
por 27.08.2013 / 00:31
0

E aqui está o Perl:

perl -ne 'if(/^Name\s*=\s*(.+)/){$n=$1;}else{print "$n $_" unless /^End/}' file

EXPLICAÇÃO

perl -ne significa processar o arquivo de entrada linha a linha ( -n ), salvando cada linha na variável $_ e executando o script fornecido como um parâmetro para -e .

if(/Name\s*=\s*(.+)/){$n=$1;} : se a linha começar com Name = <something> , salve <something> como $n .

Senão, se a linha não começar com Name , imprima o valor atual de $n , o nome e o resto da linha, a menos que essa linha seja End .

    
por 27.08.2013 / 15:19