Faz uma lista com o awk

3

Me desculpe se isso é extremamente elementar, mas não consigo descobrir como fazer isso e minha pesquisa também falhou comigo.

Eu tenho dois arquivos: data.csv e list.txt. Veja um exemplo de como eles se parecem

data.csv:

"John","red","4"
"Basketball","orange","2"
"The Mike","blue","94"
"Lizard","purple","3"
"Johnny","pink","32"

list.txt:

Mike
John
purple
32

Agora, estou tentando descobrir como posso fazer um loop

awk -F "\"*,\"*" '/**LIST ITEM**/ {print $1}' data.csv > output.txt

em que o comando é executado para cada linha de list.txt, substituindo ** LIST ITEM **. Como isso pode ser feito?

Estou rodando isso apesar do Terminal no MacOSX 10.5.7.

EDITAR:

A saída desejada para o exemplo acima seria

The Mike
John
Johnny
Lizard
Johnny

EDIT2:

Para ser mais claro, estou tentando evitar fazer isso:

awk -F "\"*,\"*" '/Mike/ {print $1}' data.csv
awk -F "\"*,\"*" '/John/ {print $1}' data.csv
awk -F "\"*,\"*" '/purple/ {print $1}' data.csv
awk -F "\"*,\"*" '/32/ {print $1}' data.csv

E, em vez disso, execute-o em um comando, de alguma forma, percorrendo todas as linhas do list.txt.

    
por Julien 09.03.2011 / 06:29

3 respostas

2

Isso atende à ordem de sua saída desejada:

$ awk -F, '
    NR == FNR {field1[$0] = $1; next}
    {
      for (line in field1) 
        if (line ~ $0) 
          print field1[line]
    }
  ' data.csv list.txt 
"The Mike"
"John"
"Johnny"
"Lizard"
"Johnny"

Isto lê o arquivo data.csv na memória, mapeando a linha inteira para o campo1. Em seguida, cada linha do arquivo list.txt é verificada em relação a cada elemento da matriz field1.

Se o arquivo de dados for muito maior do que o arquivo da lista, faria mais sentido manter o arquivo menor na memória e repetir o arquivo maior uma linha por vez:

$ awk -F, '
    NR == FNR {list[$1]; next}
    {
      for (item in list) 
        if ($0 ~ item) 
          print $1
    }
  ' list.txt data.csv 
"John"
"The Mike"
"Lizard"
"Johnny"
"Johnny"
    
por 09.03.2011 / 07:20
2
#!/bin/bash

 while read -r line; do 
   awk -F '^"|","|"$' '$0 ~ line{print $2}' line="$line" data.csv
 done < list.txt

Prova de Conceito

$ while read -r line; do awk -F '^"|","|"$' '$0 ~ line{print $2}' line="$line" data.csv; done < list.txt
The Mike
John
Johnny
Lizard
Johnny

Esse separador de campo lida com aspas e / ou vírgulas incorporadas

    
por 09.03.2011 / 07:10
1

Não estou totalmente claro sobre o que você está tentando fazer: substituir LIST ITEM por quê? Apenas procurando por uma partida em qualquer lugar e produzindo o primeiro campo? Além disso, seu exemplo list.txt parece corresponder a qualquer lugar na linha, o que poderia ser problemático: e se list.txt em algum momento contiver a linha e ? Isso corresponderia a todos, menos à última linha da sua amostra data.csv .

awk -F '^"?|"?,"?|"$?' 'BEGIN {
                          # read list.txt into an array
                          while (getline pat < "list.txt") {
                            pats[pat] = 1
                          }
                          close("list.txt")
                        }
                        {
                          # skip empty field before leading "
                          if ($1 == "") {
                            res = $2
                          } else {
                            res = $1
                          }
                          # scan record for patterns stored earlier,
                          # output the first real data field (res) if
                          # found
                          for (pat in pats) {
                            if ($0 ~ pat) {
                              print res
                            }
                          }
                        }' data.csv

Isso é um pouco mais complexo do que poderia ser; seu separador de campo não lida com as aspas principais opcionais no primeiro campo ou com o aspas opcionais no último campo. O meu faz, mas ao preço que, se estiver lá, o primeiro campo estará vazio (a string vazia antes de ^"? ). Ele também não tenta lidar com cotações incorporadas. Um analisador de CSV dedicado seria uma ideia melhor se você precisar dar suporte ao CSV generalizado aleatório.

    
por 09.03.2011 / 07:08

Tags