awk quando ambos delimitador e aspas são usados para um campo

7

Eu tenho um arquivo no seguinte formato:

field1|field2|field3
field1|"field2|field2"|field3

Observe que a segunda linha contém aspas duplas. A string entre as aspas duplas pertence ao campo 2. Como extrair isso usando o awk? Eu estive googling sem resultados. Eu tentei isso sem sorte também

FS='"| "|^"|"$' '{print $2}'  
    
por user2773013 23.10.2015 / 17:25

3 respostas

9

Se você tem uma versão recente de gawk , está com sorte. Há o recurso FPAT , documentado aqui

awk 'BEGIN {
 FPAT = "([^|]+)|(\"[^\"]+\")"
}
{
 print "NF = ", NF
 for (i = 1; i <= NF; i++) {
    sub(/"$/, "", $i); sub(/^"/, "", $i);printf("$%d = %s\n", i, $i)
 }
}' file

NF =  3
$1 = field1
$2 = field2
$3 = field3
NF =  3
$1 = field1
$2 = field2|field2
$3 = field3
    
por 23.10.2015 / 17:39
1

Isso é algo que você recebe em csv - se o delimitador fizer parte do campo, ele será citado. Isso de repente torna a tarefa de analisá-lo MUITO mais difícil, porque você não pode simplesmente dividir em um delim.

Felizmente, se perl for uma opção, você tem o módulo Text::CSV que lida com este caso:

#!/usr/bin/env perl
use strict;
use warnings;

use Text::CSV;

my $csv = Text::CSV -> new ( { 'sep_char' => '|' } );

while ( my $row =  $csv -> getline ( *STDIN ) ) {
   print $row -> [1],"\n";
}

Provavelmente poderia condensar isso em um inline / pipeable se você preferir - algo como:

perl -MText::CSV -e 'print map { $_ -> [1] ."\n" } @{ Text::CSV -> new ( { 'sep_char' => '|' } ) -> getline_all ( *ARGV )};
    
por 23.10.2015 / 18:32
-2

Você pode formatar esses dados com sed para que possa ser analisado por awk mais facilmente. por exemplo:

$ sed 's/"//g' awktest1.txt 
field1|field2|field3
field1|field2|field2|field3

$ sed 's/"//g' awktest1.txt > awktest2.txt

$ awk 'BEGIN {FS = "|"} ; {print $2}' awktest2.txt 
field2
field2

Mas, novamente, não sei a natureza dos dados com os quais você está trabalhando.

    
por 23.10.2015 / 17:37

Tags