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 :
-
awk
opera 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.txt
para 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}
.awk
tem 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 $2
etc referencia os campos e$0
referencia o registro inteiro. Por acima, esta ação é executada apenas para linhas emkey.txt
, por exemplo, na última linha do arquivo$1
é3
e$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 dek
sã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.gsub
opera no registro atual$0
por padrão. Depois de fazer essa substituição para todos os valores ema
, ele executaprint
, o que, por padrão, gera$0
como 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.