Você tem a idéia básica correta de dividir a tarefa em duas rodadas, mas então você invoca o awk dentro de uma regra do awk. É onde eu parei de ler; é uma maneira muito complicada de resolver um problema tão simples.
Considere este snippet do awk:
awk 'BEGIN {
RS = "[\t\v\f ]*(\r\n|\n\r|\r|\n)";
FS = "[\t\v\f ]+"
}
FNR==1 {
file++
}
/^#/ {
next
}
file==1 {
port[$1] = $1
}
file>=2 && ($3 in port) {
base = $3;
sub(/-[^-]*$/, "", base);
$4 = "InitFileB-" base "-username-ALPHA-password";
$5 = "OutFileB-" base "-username-ALPHA";
}
file>=2 {
printf "%s\n", $0
} ' ports.lst master.tbl
Observação: adicionei os pontos-e-vírgulas necessários para que você possa escrever todos os itens acima em uma única linha.
Se você executar o exemplo acima com os arquivos de entrada de exemplo, obterá
losangeles-P1
losangeles-P3
servername HAWAII-A hawaii-P1 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P2 InitFileB-hawaii-username-ALPHA-password OutFileB-hawaii-username-ALPHA otherfields
servername HAWAII-A hawaii-P4 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P1 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P2 InitFileA OutFileA otherfields
servername DALLAS-A dallas-P3 InitFileA OutFileA otherfields
servername LOSANGELES-A losangeles-P2 InitFileA OutFileA otherfields
A regra BEGIN
apenas define o suporte universal de nova linha, caso os arquivos tenham sido transferidos de algum outro sistema (Windows, por exemplo) com uma nova codificação de nova linha.
A regra FNR==1
é usada para atualizar a variável file
, para que ela reflita o arquivo que está sendo processado (1 para primeiro, 2 segundos).
A regra /^#/ { next }
ignora todas as linhas que começam com uma marca de hash. Eles são comentários, então eles não precisam ser mantidos. Poderíamos também adicionar uma regra /^[\t\v\f ]*$/ { next }
para pular todas as linhas vazias, se você quisesse compactar o arquivo de saída.
A regra file == 1 { port[$1] = $1 }
adiciona todos os primeiros campos do primeiro arquivo à matriz associativa port
. O valor atribuído ( = $1
) não importa, portanto, poderíamos usar apenas = 0
aqui.
A regra file >= 2 && ($3 in port)
aplica-se ao segundo e aos arquivos a seguir e é executada se o terceiro campo corresponder a uma das chaves na matriz associativa port
. (Os valores não importam; apenas as teclas são verificadas.) Em outras palavras, essa regra é aplicada apenas quando o terceiro campo é uma das chaves especificadas na lista de portas.
O terceiro campo é copiado para uma variável base
- isso corresponde a uma das chaves em port[]
- e tudo após o último -
é removido usando sub()
. Então, modificamos o quarto e quinto campos. Note que no awk não existe um operador de concatenação de strings; nós apenas declaramos as cordas próximas umas das outras. Em outras palavras, ("foo" a "bar")
é uma string, consistindo de "foo", imediatamente seguida pelo valor da variável a
convertido em uma string, imediatamente seguida por "bar".
A regra final imprime o registro (possivelmente modificado), mas garante que \n
newline seja usada. Apenas os registros no segundo e nos arquivos subseqüentes são usados.
Agora, se ports.lst
continha os nomes de usuário e senhas respectivos, eu modificaria um pouco o acima (talvez três linhas mudaram?), mas espero que você possa ver a abordagem geral.