Iterar sobre algum padrão usando shell

0

Eu tenho um arquivo para processar e obter algumas entradas dele. O formato do arquivo é:

Exemplo de entrada:

String1:"Hello"
String2:"World"
String3:"Question"
End
String1:"HelloAgain"
String5:"Answer"
End
String1:"NewEntry"
String2:"Foo"
String5:"NewFile"
End

O script irá iterar e tentar localizar String1 e imprimi-lo, se String2 também estiver presente nesse bloco, anexá-lo a String1 e imprimir.

Exemplo de saída:

Hello World
HelloAgain
NewEntry Foo

Eu preciso percorrer cada bloco. O que quero dizer com um bloco aqui é conteúdo entre cada string "End". Eu tenho um script como:

    cat $1 | while read line
do
    if [[ $line == "String1="* ]];
    then
        string1=$line
    fi
    if [[ $line == "String2="* ]];
    then
        string2=$line
    fi
    if [[ $line == "End" ]];
    then
        if [ $string1 ];
            then
            echo "string1/"$string1"
        fi
        if [ $string1 ] && [ $string2 ];
            then
            echo $string1" "$string2
        fi
    #Reset values
    string1=''
    string2=''
    fi
done

Esse código funciona bem, mas o processamento entre esses blocos pode se tornar mais complexo, o que é a melhor maneira de iterar esses blocos e processar essas entradas de bloco.

NOTA: O arquivo é uma espécie de arquivo de propriedades.

    
por leo195 27.07.2017 / 19:58

2 respostas

0

Dada sua entrada fornecida e a saída solicitada:

$ awk -F: '$0 == "End" { printf "\n" } $1 ~ /^String[12]$/ { gsub( /\"/, "", $2 ); printf( "%s ", $2)}' input
Hello World
HelloAgain
NewEntry Foo
    
por 27.07.2017 / 21:07
0
perl -F':|"' -lane 'if ($out && $_ eq "End") {print "$out"; $out=""};
  $out  = $F[2] if ($F[0] eq "String1");
  $out .= $F[2] if ($out && $F[0] eq "String2")' input.txt

Esse script perl usa : ou " como o separador de campo, para evitar a necessidade de retirar aspas duplas da saída. Isso significa que precisamos extrair o campo third em vez do segundo, pois agora há um campo vazio entre o primeiro : e o " . Arrays Perl são baseados em zero, então é $F[2] .

Ele imprime apenas a saída para um registro ("bloco") se houver algo para imprimir, ou String1 por si só ou String1 e String2 estão presentes - isto é, ele não imprime linhas em branco para registros não correspondentes.

Este é o mesmo algoritmo em awk :

awk -F':|"' 'out && $0 == "End"  { print out; out="" };
  $1 == "String1" { out=$3 };
  out && $1 == "String2" { out = out$3 }' input.txt
    
por 30.07.2017 / 07:13