field-names.txt contém uma lista de nomes de campos:
AB_CODE
ACFT_CODE
AC_TYPE
ADD_INFO
AKA
ALT
ALT1_DESC
ALT2_DESC
ALT3_DESC
Para cada nome de campo, quero imprimir os arquivos cuja primeira linha contém esse nome de campo (uma lista de campos separados por espaços). Aqui está o que tentei:
Em uma bash
linha de comando, digitei isto:
cat field-names.txt | awk 'BEGIN { getline fieldname; print fieldname }
NR == 1 && $0 ~ /fieldname/ { print FILENAME }' **/*.TXT
Isso produz o resultado errado. Qual é a maneira correta de fazer isso?
Esta
awk
solução deve funcionar para você:Primeiro, construímos um regex com
|
entre cada linha defield-names.txt
no primeiro bloco deFNR == NR
. Então, usamos esse regex para corresponder a cada primeira linha usando esse regex. Prefixamos e sufixamos cada primeira linha e regex com espaço para garantir que correspondemos apenas à palavra inteira, não às parciais .Para fins de otimização, podemos fazer assim para construir uma regex completa apenas uma vez:
(cálculo de afre cortesia do comentário de @Ed Morton)
Reservamos um tempo no início para calcular a regex para qualquer um dos campos considerados,
para que o "loop" principal possa então ser executado na velocidade máxima.
E como olhamos apenas na primeira linha, depois de pesquisar, usamos um nextfile incondicionalmente para alternar para o próximo arquivo de entrada, independentemente de termos uma correspondência ou não.
Qual solução escolher?
Então, a diferença com a solução de @anubhava (da qual também gostei e votei: para meus dois primeiros tópicos, a solução que você escolher é uma questão de gosto) é:
^
e$
para corresponder como o primeiro ou último campo, mas costumo usar o truque dos espaços adicionais também
Otimização adicional
Observe que, dependendo da implementação do awk, ele
$0 ~ afre
pode recompilar o regex em cada linha (por ser uma variável, ele pode... variar, portanto, o awk precisa verificar se ele não mudou se quiser armazenar em cache a versão compilada do regex).Ao executá-lo pelo shell, você pode forçá-lo a uma regex fixa (mais facilmente otimizável) com um (reconhecidamente menos legível):
Supondo que você queira gerar um mapa de nomes de campos para os arquivos em que eles ocorrem, use qualquer awk (não testado):
Isso funcionará independentemente se os nomes dos arquivos de destino contêm metachars regexp
.
ou não.Mude
"* Not found *"
para alguma outra string ou faça o que quiser para manipular campos de destino que não existem em nenhum arquivo de entrada. Se quiser usar algum outro separador que não seja um caractere em branco entre o nome do campo e cada nome de arquivo associado, basta definirOFS
para qualquer string que preferir.Uma alternativa que não usa regex, pois parece que a lista de nomes de campos são apenas strings simples:
Este código também aceita nomes de campos no início e no fim de uma linha.