Awk - gera a segunda linha de vários arquivos .dat em um arquivo

8

Eu pesquisei as perguntas feitas anteriormente e não consigo encontrar uma resposta para o que estou tentando fazer. note, eu sou novo no linux.

Eu tenho vários arquivos como: (na verdade eu tenho 80)

file1.dat

2 5

6 9

7 1

file2.dat

3 7

8 4

1 3

Eu quero acabar com um arquivo contendo todas as segundas linhas. ou seja,

output.dat

6 9

8 4

O que eu tenho até agora faz um loop nos nomes dos arquivos, mas depois sobrescreve o arquivo antes dele. por exemplo. a saída dos arquivos acima seria apenas

8 4

meu script de shell é assim:

post.sh

TEND = 80

TINDX = 0

while [ $TINDX - lt $TEND]; do

awk '{ print NR==2 "input-$TINDX.dat > output.dat

TINDX = $((TINDX+1))

done

muito obrigado por qualquer ajuda com isso

    
por Rowland 13.01.2015 / 10:56

6 respostas

14

Remova o while do loop e faça uso da expansão da chave de concha e também FNR , uma variável awk incorporada:

awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat
    
por 13.01.2015 / 11:19
7

sed seria suficiente:

sed -sn 2p file{1..80}.dat > output.dat
A opção

-s é necessária para imprimir a segunda linha de cada arquivo, caso contrário, somente a segunda linha do primeiro arquivo será impressa.

    
por 13.01.2015 / 13:01
5

Que tal ... head -n 2 input.dat | tail -n 1 | awk ...

    
por 13.01.2015 / 12:41
2

A solução sed da aragaer é a mais legal, sim. Mas como gosto de um pouco de head|tail de corte, tenho uma solução head|tail que suporta vários arquivos, não apenas um único input.dat . Usando um loop for, em vez de passar uma lista de arquivos para sed, também torna mais fácil fazer outra coisa com o arquivo antes / depois de extrair a segunda linha com sed.

# empty output.dat first
rm output.dat

# have a one-liner
for file in *.dat; do head -2 $file | tail -1 >> output.dat; done 

Versão multi-linha copiosamente comentada:

NB: o código abaixo será executado. Temos a liberdade de colocar um quebra de linha após um | , && ou || e continuar nosso comando na próxima linha; Podemos até colocar comentários no meio. Passei anos sem saber (e não vendo em nenhum lugar). Esse estilo é menos útil no prompt interativo, mas limpa os arquivos de script sem fim.

# empty output.dat first
rm output.dat

for file in *.dat; do
    # file -> lines 1 and 2 of file
    head -2 $file |
    # lines 1 and 2 of file -> line 2 of file >> appended to output.dat
    tail -1 >> output.dat
done
    
por 13.01.2015 / 13:59
0

Existem, obviamente, muitas maneiras de fazer isso - acho que eu gosto @saga do aragaer responde melhor .

Aqui está um que usa recursos puramente básicos e não precisa usar nenhum utilitário externo:

for f in file{1..80}.dat; do
    { read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat
    
por 13.01.2015 / 18:05
0

Para uso eficiente de awk e sed em respostas aqui em vários arquivos, é melhor usar a instrução nextfile para ignorar o processamento de linhas indesejadas em awk .

awk 'FNR==2{ print >"output.dat"; nextfile}' infile{1..80}.dat

e com sed , podemos sair quando processamos na linha 3 rd e sed processará o próximo arquivo.

sed -sn '2p;3q' infile{1..80}.dat > output.dat
    
por 03.04.2018 / 10:29