Estou usando o código a seguir para extrair informações de vários arquivos de texto (foo*.txt).
for file in foo*.txt; do
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar.csv
done
Este comentário imprime os números que desejo de vários arquivos (foo*.txt). Quando tento imprimir o nome do arquivo (em uma coluna do arquivo csv) e o número (na próxima coluna do arquivo csv), tentei seguir no Terminal.
for file in foo*.txt; do
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}' >> bar2.csv
done
Isso imprime os nomes dos arquivos no terminal. O arquivo csv contém os números que desejo. Como esse código pode ser modificado para que o nome do arquivo seja impresso em uma coluna e os números extraídos na próxima coluna do arquivo csv?
Outro problema neste código é o problema de classificação. Por exemplo, considere os nomes de arquivo foo_01_s.txt, foo_02_s.txt, foo_03_s.txt.....foo_100_s.txt. Se eu quiser extrair informações (usando os comentários acima), o último arquivo (foo_100_s.txt) não vem depois de foo_99_s.txt.
Uma solução usando Python/Perl também seria útil.
Responder1
Você tem que entender que >>
irá redirecionar apenas a parte do comando atual - basicamente apenas o número que é o resultado do comando começando com grep
e canalizado algumas vezes. echo $file
é um comando separado (você usa ;
) e, portanto, normalmente direcionará para stdout. Tudo que você precisa fazer é redirecionar após todo o loop:
for file in foo*.txt; do
echo $file
grep "some_text" $file | tail -n5 | awk '{print $2}'
done > bar2.csv
Se você deseja classificar seus arquivos por "versão" (este é o nome apropriado), você pode listá-los após a classificação:
for file in $(ls foo*.txt | sort -V); do
para executar algo pequeno rapidamente (alguns minutos para cerca de 1000 arquivos), isso deve servir.
EDITAR
Após seu comentário, existem algumas soluções. Acho que você quer:
file1 1
2
3
etc. Basta descartar echo
e alterar a linha de eco:
for file in foo*.txt; do
grep "some_text" $file | tail -n5 | awk -v f=$file '{if(NR==1) {printf("%-20s %-5s\n",f,\$2)} else {printf("%-20s %-5s\n","",$2)}}'
done > bar2.csv
Deixei awk
fazer a impressão para mim. Usar -v
me permite passar uma variável em f
. Para a impressão, familiarize-se com printf
a sintaxe (você pode usar man printf
no shell. Basicamente, estou assumindo dois campos, um com 20, o outro com 5 e um espaço entre eles. O sinal negativo justifica à esquerda. Você pode brincar com isso. Isso seria corrigiu seu problema inicial, já que agora você pode canalizar essa única linha.
Se você quiser que o arquivo seja apenas:
file1,1
file1,2
...
file2,1
você pode descartar if
minha awk
declaração ou deixar a solução inicial com echo, mas use,
echo -n "$file,"
onde -n
garante que nenhuma nova linha seja impressa.