Awk - affiche la deuxième ligne d'un certain nombre de fichiers .dat dans un fichier

9

J'ai plusieurs fichiers quelque chose comme: (en réalité, j'en ai 80)

file1.dat

2 5

6 9

7 1

file2.dat

3 7

8 4

1 3

Je veux me retrouver avec un fichier contenant toutes les secondes lignes. c'est à dire

output.dat

6 9

8 4

Ce que j'ai jusqu'ici fait une boucle sur les noms de fichiers mais écrase ensuite le fichier avant lui. par exemple, la sortie des fichiers ci-dessus serait juste

8 4

mon script shell ressemble à ceci:

post.sh

TEND = 80

TINDX = 0

while [ $TINDX - lt $TEND]; do

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

TINDX = $((TINDX+1))

done
Rowland
la source

Réponses:

17

Supprimez la whileboucle et utilisez l'expansion de l'accolade du shell et également FNRune awkvariable intégrée :

awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat
jimmij
la source
9
encore plus courtawk 'FNR==2' file{1..80}.dat > output.dat
Archemar
7

Et head -n 2 input.dat | tail -n 1 | awk...

HarveyP
la source
Oui, head/ tailest définitivement une option, vous n'avez pas besoin awkalors.
jimmij
7

sed serait suffisant:

sed -sn 2p file{1..80}.dat > output.dat

-s l'option est nécessaire pour imprimer la 2e ligne de chaque fichier, sinon seule la 2e ligne du premier fichier sera imprimée.

aragaer
la source
2

La sedsolution d'Aragaer est la plus agréable, oui. Mais depuis que j'apprécie un peu la head|taildécoupe, j'ai une head|tailsolution qui prend en charge plusieurs fichiers, pas seulement un seul input.dat. L'utilisation d'une boucle for, au lieu de transmettre une liste de fichiers à sed, facilite également d'autres tâches avec le fichier avant / après l'extraction de la deuxième ligne avec 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 

Version multi-lignes abondamment commentée:

NB: le code ci-dessous s'exécutera. Nous sommes libres de mettre un saut de ligne après |, &&ou ||, et continuer notre commande sur la ligne suivante; nous pouvons même mettre des commentaires entre les deux. J'ai passé des années à ne pas le savoir (et à ne le voir vraiment nulle part). Ce style est moins utile à l'invite interactive, mais nettoie les fichiers de script sans fin.

# 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
Esteis
la source
0

Il y a évidemment beaucoup de façons de le faire - je pense que j'aime mieux la réponse sed de @ aragaer .

En voici un qui utilise uniquement des commandes internes bash et n'a pas besoin de bifurquer d'utilitaires externes:

for f in file{1..80}.dat; do
    { read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat
Traumatisme numérique
la source
0

Pour une utilisation efficace de awket seddans les réponses ici sur plusieurs fichiers, mieux vaut utiliser l' nextfileinstruction pour ignorer le traitement des lignes indésirables dans awk.

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

et avec sed, nous pouvons quitter lors du traitement sur la 3 ème ligne et sedtraiter le fichier suivant.

sed -sn '2p;3q' infile{1..80}.dat > output.dat
αғsнιη
la source