Como observado em meu comentário, a menos que exista algo que você não tenha nos contado, não parece haver necessidade de usar descritores de arquivos além de stdin e stdout aqui, nem há qualquer razão para não apenas passar os nomes de arquivos para awk
na linha de comando.
E gravar um loop while read
do shell para executar awk
várias vezes no mesmo arquivo de entrada é uma maneira realmente difícil de fazer o que você está tentando fazer - possivelmente a pior maneira possível de processar arquivos de texto. Serão centenas ou milhares de vezes mais lentas do que fazer a mesma tarefa no awk (ou sed ou perl, etc.).
Tente algo assim:
#!/bin/bash
FILE1="$1"
FILE_TO_SEARCH="$2"
awk 'NR==FNR { gsub(/([\.^$(){}\[\]|*+?])/,"\\&",$0);
if (search == "") {
search = $0;
} else {
search = search "|" $0;
};
next;
};
match($0,search)' "$FILE1" RS='' ORS='\n\n' "$FILE_TO_SEARCH"
(feeds de linha, recuo adicionado para legibilidade. a parte awk deste trabalho é toda comprimida em uma linha também)
Isso imprimirá todos os registros em $FILE_TO_SEARCH
que correspondem a qualquer um dos padrões de pesquisa em $FILE1
.
Ele lê o primeiro arquivo ( $FILE1
) usando o padrão RS
& ORS
e constrói um padrão de procura de expressão regular a partir dele. A chamada da função gsub()
é usada para excluir todos os meta-caracteres da expressão regular antes de cada linha ser anexada ao padrão de pesquisa, ou seja, todas as linhas são tratadas como sequências fixas. Se você quiser que cada linha seja uma expressão regular, consulte a segunda versão abaixo.
Com sua amostra $FILE1
acima, o padrão de pesquisa será:
hostAbC|host123|host345|hostMos|hostDef
Em seguida, usando RS=''
e ORS='\n\n'
, ele lê o segundo arquivo ( $FILE_TO_SEARCH
) e imprime qualquer registro que corresponda ao padrão de pesquisa.
A seguinte versão pode ser usada se você quiser que cada linha de $FILE1
seja interpretada como uma expressão regular em vez de uma string fixa:
#!/bin/bash
FILE1="$1"
FILE_TO_SEARCH="$2"
awk 'NR==FNR { if (search == "") {
search = "(" $0 ")" ;
} else {
search = search "|(" $0 ")";
};
next;
};
match($0,search)' "$FILE1" RS='' ORS='\n\n' "$FILE_TO_SEARCH"
O padrão de pesquisa da amostra com esta versão seria:
(hostAbC)|(host123)|(host345)|(hostMos)|(hostDef)
Observe que, com essa versão, é possível construir facilmente um padrão de pesquisa interrompido que não corresponda a nada ou que corresponda demais. Você precisará usar a barra invertida para escapar de quaisquer meta-caracteres regex em $ FILE1 que você queira que sejam interpretados como sequências literais. por exemplo. Se você quiser combinar um literal |
, ele deve estar no arquivo como \|
, caso contrário, ele será interpretado como um operador de alternância regex OR
.