Extraia substrings de cada linha. Essas subseqüências estão no formato separado por vírgula, “name = value”

2

Eu tenho linhas em um arquivo separado por vírgulas. Não há cabeçalhos de coluna, é principalmente pares 'name = value' separados por vírgulas. Aqui estão alguns dados de teste:

listoffruits,producelist,APPLE=red,BANNANA=yellow,GRAPE=purple,ORANGE=orange,FRUIT=yes,WATERMELON=green
listoffruits,producelist,APPLE=red,BANNANA=yellow,GRAPE=violet,ORANGE=orange,FRUIT=affirmative,WATERMELON=green

Gostaria de obter o valor de GRAPE = * e FRUIT = * para obter o resultado:

purple yes
violet affirmative

Além disso, gostaria de poder adicionar mais "colunas" mais tarde (portanto, nem sempre UVA, FRUTA, mas UVA, FRUTA e MELANCIA)

Outro problema é que as colunas não são fixas. Então, eu nem sempre sei que o WATERMELON é a última coluna.

O mais perto que cheguei foi de @jasonwryan:

awk -v RS="," -F= '/GRAPE/{a=$2}; /FRUIT/{b=$2} END{print a,b"\n"}'

mas isso produz a última linha "afirmativa violeta" e não:

purple yes

violet affirmative
    
por patronizing_bofh 09.05.2015 / 07:32

2 respostas

4

Mais algumas escolhas. Salvei seu texto de exemplo em file para simplificar.

  1. grep e PCREs:

    $ grep -oP '(GRAPE|FRUIT)=\K.*?(?=,)' file 
    purple
    yes
    violet
    affirmative
    

    Para colocá-los na mesma linha, basta analisar. Por exemplo

    $ grep -oP '(GRAPE|FRUIT)=\K.*?(?=,)' | paste -d" " - - –  
    purple yes
    violet affirmative
    
  2. sed

    $ sed 's/.*GRAPE=\([^,]*\).*FRUIT=\([^,]*\).*/ /' file 
    purple yes
    violet affirmative
    

    Ou com o GNU sed

    $ sed -r 's/.*GRAPE=([^,]*).*FRUIT=([^,]*).*/ /' file 
    purple yes
    violet affirmative
    
  3. Perl

    $ perl -pne 's/.*GRAPE=([^,]*).*FRUIT=([^,]*).*/ /' file 
    purple yes
    

    Você pode notar que o acima é um pouco semelhante ao sed one :). Alternativamente:

    $ perl -lne '@f=(/(?:(?<=GRAPE=)|(?<=FRUIT=))(.+?),/g); print "@f"' file 
    purple yes
    violet affirmative
    

    Isso usa , como separador de campo e pesquisa todos os campos:

    $ perl -F, -lane '@r=grep(s/.+?=//, grep(/GRAPE|FRUIT/,@F)); print "@r"' file 
    purple yes
    violet affirmative
    

    Este é mais curto, mas adiciona um espaço inicial a cada linha:

    $ perl -F, -lane 'print grep(s/.+?=/ /, grep(/GRAPE|FRUIT/,@F));' file 
     purple yes
     violet affirmative
    
por 09.05.2015 / 12:13
2

Usando o Awk:

awk -v RS="," -F= '/GRAPE/||/FRUIT/ {printf "%s ", $2}'

Altera o separador de registro de uma nova linha para , e o separador de campo de um espaço para = , depois combina linhas que contêm o padrão GRAPE ou FRUIT e imprime o segundo campo correspondente na mesma linha separada por um espaço. Resultado:

purple yes 
    
por 09.05.2015 / 07:49