Procura por valores em 2 colunas do CSV

5

Eu tenho um arquivo csv com 20 colunas ímpares.

Eu preciso obter os valores da 14ª e 15ª coluna em que o valor na 14ª coluna é "VALUE1" e o valor na 15ª coluna é "VALUE2" .

Minha condição fica satisfeita apenas quando a 14ª coluna tem VALUE1 e a 15ª coluna tem VALUE2 . Preciso obter a contagem agregada.

Acho que wc -l poderia me fornecer a lista de contagem e cut -d "," -f14,15 me dá os valores da coluna 14 e 15. Mas como verificar se o 14o tem VALUE1 e 15 tem VALUE2 ?

Acho que o abaixo funciona

grep -r "" * | cut -d " " -f14,15 | grep "Value1" | grep "Value2"

mas ainda não acho que essa é a maneira perfeita de fazer isso.

    
por Ebbu Abraham 18.02.2012 / 10:42

3 respostas

4

awk poderia ser mais útil aqui.

Por exemplo:

$> echo "a b c d e" | awk '$2=="b" && $3=="c" {print}'
a b c d e

$> echo "a b c d e" | awk '$2=="a" && $3=="c" {print}'

$> echo "a b c d e" | awk '$2=="b" && $3=="d" {print}'

Então, responda a sua pergunta:

awk '$14=="VALUE1" && $15=="VALUE2" {print}'

    
por 18.02.2012 / 10:49
1

Se awk não estiver disponível, você poderá fazer isso com cut , grep e wc :

$ echo -e 'a,b, c,d\na,val1 ,val2,c' \
   | cut -d ',' -f2,3 | grep '^ *val1 *, *val2 *$' | wc -l

Assumindo , como delimitador (e de forma alguma escapou , é incluído) na entrada. Para fins de teste, as colunas 2 e 3 são usadas em vez de 14 e 15.

Observe que o padrão grep permite espaços em branco finais após / antes dos valores (é possível remover os sub-padrões * se você não quiser isso). Os meta-caracteres ^ e $ correspondem ao início e ao final de uma linha.

O canal grep "Value1" | grep "Value2" de sua pergunta não faz o que você especifica - ele corresponderia muito, por exemplo:

    ..., Value1Value2, , ...
    ..., Value1, Value2, ...
    ..., OtherValue1, Value2, ...
    ...

Se awk estiver disponível (é bem normal), você pode fazer assim:

$ echo -e 'a,b, c,d\na,val1,val2,c' \
    | awk -F, '$2 == "val1" && $3 == "val2" {++sum} END {print sum}'

awk apara automaticamente os espaços em branco dos valores. END é um padrão especial que corresponde depois de todas as linhas serem processadas.

    
por 18.02.2012 / 11:38
0

A função a seguir usará apenas Bash para fazer o que você deseja:

foo () 
{ 
    local filename="$1";
    while IFS=, read -ra arr; do
        if [[ "${arr[13]}" = "VALUE1" && "${arr[14]}" = "VALUE2" ]]; then
            printf '%s\n' "${arr[13]}" "${arr[14]}";
        fi;
    done < "$filename"
}

Uso: foo [/path/to/file.txt]

Exemplo de saída:

rany$ cat > source.txt 
a,a,a,a,a,a,a,a,a,a,a,a,a,VALUE1,VALUE2
a,a,a,a,a,a,a,a,a,a,a,a,a,NOMATCH1,NOMATCH2
a,a,a,a,a,a,a,a,a,a,a,a,a,VALUE1,VALUE2

rany$ foo source.txt
VALUE1
VALUE2
VALUE1
VALUE2
    
por 16.04.2013 / 23:32