Como aplicar a mesma ação awk em arquivos diferentes?

8

Eu sou novo no awk e não sei se é possível escrever um script awk que faça isso:

Eu tenho centenas de arquivos de dados que eu tenho que classificar. Para cada um eu uso o seguinte one-liner:

awk 'ORS=NR%3?" ":"\n" ' file1.tex >  file1_sorted.tex
awk 'ORS=NR%3?" ":"\n" ' file2.tex >  file2_sorted.tex
...

e eu recebo a saída de que preciso. No entanto, gostaria de ter um script para automatizar essa ação, pegando cada arquivo, aplicando a ação e escrevendo o arquivo classificado correspondente.

Eu agradeceria sua ajuda!

    
por Nacu 19.02.2012 / 13:48

3 respostas

7

Se você modificar o código awk , pode ser resolvido por um único processo awk e nenhum loop de shell:

awk 'FNR==1{if(o)close(o);o=FILENAME;sub(/\.tex/,"_sorted.tex",o)}{ORS=FNR%3?" ":"\n";print>o}' *.tex

Não é uma beleza, apenas insignificantemente mais rápida.

Explicações conforme solicitado no comentário.

FNR ( f ile n umber ou r ecord) é semelhante a NR ( n umber ou r ecord), mas enquanto NR é um número sequencial contínuo de todos os registros de entrada, FNR é redefinido para 1 quando o processamento de um novo arquivo de entrada é iniciado.

Uma alternativa somente gawk 4.0 para o FNR==1 é o padrão especial BEGINFILE .

awk '
FNR==1{   # first record of an input file?
  if(o)close(o);   # was previous output file? close it
  o=FILENAME;sub(/\.tex/,"_sorted.tex",o)   # new output file name
}
{
  ORS=FNR%3?" ":"\n";   # set ORS based on FNR (not NR as in the original code)
  print>o   # print to the current output file
}
' *.tex
    
por 20.02.2012 / 11:38
12

Você pode aplicar os arquivos em um loop:

for file in *.tex;
do
    awk 'ORS=NR%3?" ":"\n"' "$file" > "$(basename "$file")_sorted.tex"
done

Ou em uma linha:

for file in *.tex; do awk 'ORS=NR%3?" ":"\n"' $file > "$(basename "$file" .tex)_sorted.tex"; done

Como você não especifica qual shell, use o padrão basename usando a sintaxe específica do shell ${file%%.tex} .

    
por 19.02.2012 / 14:29
0

Antiga pergunta, mas considerando que a última vez que vi um único computador pessoal central foi há uma década, você pode usar o gnu paralelo

Para resolver a expansão do shell e interpretação de citações

my_awk='ORS=NR%3?" ":"\n"' 

Use o glob adequado para selecionar os arquivos de entrada. Aqui estou usando {.} para retirar a extensão do nome da saída porque estou acrescentando depois

parallel -jX "awk '$my_awk' {} > {.}_sorted.tex" ::: *.tex

onde X é o número de processadores que você deseja usar, ainda é possível usar 1. Isso lhe daria file[1-9]_sorted.tex como saídas

    
por 17.06.2016 / 14:04

Tags