Imprimir seção específica de uma linha quando um valor de trigger está presente

3

Estou analisando dados no seguinte formato:

prop1=value1:prop2=value2:prop3=value3+prop1=value4:prop2=value5
  1. partes da string são delimitadas por +
  2. as propriedades podem aparecer em qualquer ordem
  3. a saída desejada é o valor de prop2 da parte da string onde prop1 tem um valor específico (entrada)

Posso conseguir isso por meio de ferramentas de linha de comando padrão do UNIX, ou preciso escrever um pequeno programa em C?

Editar - para a linha mostrada, esta é a funcionalidade desejada:

input: value1 -> output: value2
input: value4 -> output: value5
    
por Let_Me_Be 11.03.2014 / 13:12

7 respostas

1

Com base na resposta do devnull, eu juntei isto:

echo $LINE | tr '+' '\n' | grep "prop1=$VALUE" | tr ':' '\n' | grep "prop2=" | cut -d= -f2

Ainda estou aberto a respostas melhores.

    
por 11.03.2014 / 13:40
1

Você pode usar gawk :

awk -F'+' '{for(i=1;i<=NF;i++){if($i ~ /value1/)
               {$i=gensub(/.*prop2=(.*)(:.*|.*$)/,"\1","g",$i);print $i}}}' file
    
por 11.03.2014 / 18:55
1

Se você não se importa com o Perl:

perl -053nE '
    BEGIN{ $value = shift }
    chomp;
    tr {=:}{ };
    %h = eval "qw($_)";
    say $h{prop2} if $h{prop1} eq $value
' your_file value1

Isso não assume nenhuma ordem particular de propriedades, mas supõe que nem os nomes nem os valores das propriedades conterão espaços. Se isso não for verdade, será necessária mais análise.

Explicação

  • -053 define o separador de registro para o caractere ASCII cujo código octal é 53 , ou seja, + .
  • -n significa aplicar o trabalho em um registro por vez, alterando $_ para o conteúdo do registro.
  • -E significa executar o seguinte código com as opções anteriores em mente.

  • O código com comentários:

    perl -053nE '
        BEGIN{ $value = shift } # $value now = the command line argument
        chomp;                  # Remove the record separator (+)
        tr {=:}{ };             # Make all '=' and ':' into a space
        %h = eval "qw($_)";     # Parse the line into a hash (explained below)
        say $h{prop2} if $h{prop1} eq $value # This is your required logic
    ' your_file value1
    
    • O operador qw() usa uma lista separada por espaços e cita corretamente suas palavras constituintes para criar uma lista. Quando aplicado ao registro

      prop1 value1 prop3 value3 prop2 value2
      

      (lembre-se de como alteramos todos os + e = em um espaço), ele transforma o registro em uma lista. Quando esta lista é atribuída a uma variável hash %h , assume-se que as chaves hash são os elementos ímpares da lista e os valores hash são os pares mesmo.

por 03.08.2014 / 02:37
0

Supondo que você sempre desejará o primeiro prop1 depois , qualquer que seja o value que você passar, poderá fazer:

$ perl -lne '/prop1=value1[:+].*?prop2=([^:+]+)/ && print $1' file 
value2
$ perl -lne '/prop1=value4[:+].*?prop2=([^:+]+)/ && print $1' file 
value5

A ideia aqui é corresponder a prop1=valueN . O value4[:+] certifica-se de que todo o valor está marcado, até o próximo delimitador de campo ( : ou + ), de modo que value4 não corresponda a value44 , por exemplo. Em seguida, 0 ou mais caracteres ( .*? ), seguidos por prop2= e o valor de prop2 .

    
por 11.03.2014 / 17:32
0

Você pode tentar algo como:

awk '{
    for(i = 1; i <= NF; i++) {
        split($i, tmp, /=/)
        if(tmp[1] == "prop1") {
            printf " %s%s", "input: ",tmp[2]
        }
        if(tmp[1] == "prop2") {
            printf " %s%s", "output: ",tmp[2]
        }
     }
     print ""
}' RS='+' FS=':' file

Saída (com sua entrada de amostra):

input: value1 output: value2
input: value4 output: value5
    
por 11.03.2014 / 23:09
0
awk -F"[:=]" -vRS='+' '{for(i=1; i<=NF; i++) {if($i == "prop1") I=$(i+1); if($i == "prop2") O=$(i+1)}; printf "input: %s -> output: %s\n", I, O}' file
    
por 25.07.2014 / 19:10
0
awk -vRS='+|\n' '
    BEGIN{ p1=":prop1="; p2=":prop2=" } 
    { if( ":"$0":" ~ p1 p1val ":" ) {
        if( match(":"$0":", p2 "[^:]+:" ) ) {
          print substr($0, RSTART+length(p2)-1, RLENGTH-length(p2)-1)
    }}}' p1val=value4

Canalize sua string (ou arquivo) em awk .
O valor de prop1 é inserido por meio de uma variável-arg p1val= como mostrado.

Saída para entrada: p1val=value1

value2

Saída para entrada: p1val=value4

value5
    
por 01.06.2015 / 18:57