awk pode ser efetivamente igual a perl aqui um pouco mais simples , embora implementações diferentes do GNU possam desperdiçar um pouco de tempo de CPU desnecessariamente dividindo o ?) arquivo de texto:
awk 'NR==FNR{a["\["$1"\]"]="["$2"]";next} {for(k in a) gsub(k,a[k]);print}' key.txt essay.txt
Desde que você solicitou explicação :
-
awkopera pegando um 'script' que consiste em pares de ação padrão e lê um ou mais arquivos (ou entrada padrão) um 'registro' por vez, onde por padrão cada registro é uma linha, e para cada registro o divide em campos por padrão no espaço em branco (o que inclui a guia) e aplica o script por vez (a menos que indicado de outra forma) testando cada padrão (que geralmente analisa o registro atual e / ou seus campos) e se ele corresponde executando a ação (que geralmente faz algo para ou com o registro e / ou campos). Aqui eu especifico dois arquivoskey.txt essay.txtpara que eles leiam esses dois arquivos nessa ordem, linha por linha. O script pode ser colocado em um arquivo em vez de na linha de comando, mas aqui eu escolhi não. -
o primeiro padrão é
NR==FNR.NRé uma variável incorporada que é o Número do Registro sendo processado;FNRé similarmente o número do registro dentro do arquivo de entrada atual. Para o primeiro arquivo (key.txt) estes são iguais; para o segundo arquivo (e quaisquer outros) eles são desiguais -
a primeira ação é
{a["\["$1"\]"]="["$2"]";next}.awktem matrizes 'associativas' ou 'hash';arrayname[subexpr]ondesubexpré uma expressão com valor de cadeia lê ou define um elemento da matriz.$number, por ex.$1 $2etc referencia os campos e$0referencia o registro inteiro. Por acima, esta ação é executada apenas para linhas emkey.txt, por exemplo, na última linha do arquivo$1é3e$2ésource-three, e isso armazena uma entrada de matriz com um índice de\[3\]e um conteúdo de[source-three]; veja abaixo por que eu escolhi esses valores. Os"\["e"\]"são literais de string usando escores cujos valores reais são\[e\], enquanto"[" "]"são apenas[ ]e operandos de cadeia sem nenhum operador entre eles são concatenados. Finalmente, esta ação executanext, o que significa ignorar o resto do script para este registro, basta voltar ao início do loop e começar no próximo registro. -
o segundo padrão está vazio, portanto, ele corresponde a todas as linhas do segundo arquivo e executa a ação
{for(k in a) gsub(k,a[k]);print}. A construçãofor(k in a)cria um loop, muito parecido com shells do tipo Bourne emfor i in this that other; do something with $i; done, exceto que aqui os valores deksão os subscritos da matriza. Para cada valor, ele executagsub(substituto global), que encontra todas as correspondências de uma determinada expressão regular e as substitui por uma determinada string; Eu escolhi os subscritos e conteúdos na matriz (acima) para que, por exemplo,\[3\]seja uma expressão regular que corresponda à cadeia de texto[3]e[source-three]seja a cadeia de texto que você deseja substituir para cada correspondência.gsubopera no registro atual$0por padrão. Depois de fazer essa substituição para todos os valores ema, ele executaprint, o que, por padrão, gera$0como está agora, com todas as substituições desejadas concluídas.
Nota: GNU awk (gawk), que é comum especialmente no Linux, mas não universal, possui uma otimização onde ele não faz realmente a divisão de campos se nada nos padrões ou ações executadas precisar dos valores do campo. Em outras implementações, uma pequena quantidade de tempo de CPU pode ser desperdiçada, o que o método perl do cuonglm evita, mas a menos que seus arquivos sejam gigantescos, isso provavelmente nem será perceptível.