Awk: genera la segunda línea de varios archivos .dat en un archivo

9

Tengo varios archivos como: (en realidad tengo 80)

file1.dat

2 5

6 9

7 1

file2.dat

3 7

8 4

1 3

Quiero terminar con un archivo que contiene todas las segundas líneas. es decir

output.dat

6 9

8 4

Lo que tengo hasta ahora recorre los nombres de los archivos, pero luego sobrescribe el archivo antes. por ejemplo, la salida de los archivos anteriores sería simplemente

8 4

mi script de shell se ve así:

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
fuente

Respuestas:

17

Elimine el whilebucle y haga uso de la expansión de llave de concha y también FNR, una awkvariable integrada :

awk 'FNR==2{print $0 > "output.dat"}' file{1..80}.dat
jimmij
fuente
99
aún más cortoawk 'FNR==2' file{1..80}.dat > output.dat
Archemar el
7

¿Qué hay de ... head -n 2 input.dat | tail -n 1 | awk...

HarveyP
fuente
Sí, head/ tailes definitivamente una opción, no es necesario awkentonces.
jimmij
7

sed seria suficiente:

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

-s se necesita la opción para imprimir la segunda línea de cada archivo, de lo contrario solo se imprimirá la segunda línea del primer archivo.

aragaer
fuente
2

La sedsolución de Aragaer es la mejor, sí. Pero desde que disfruto un poco de head|tailcorte, tengo una head|tailsolución que admite múltiples archivos, no solo uno input.dat. El uso de un bucle for, en lugar de pasar una lista de archivos a sed, también facilita hacer otra cosa con el archivo antes / después de extraer la segunda línea con 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 

Versión multilínea copiosamente comentada:

NB: se ejecutará el siguiente código. Somos libres para poner un salto de línea después de una |, &&o ||, y continuar nuestro comando en la línea siguiente; incluso podemos poner comentarios en el medio. Pasé años sin saber esto (y sin verlo realmente en ningún lado). Este estilo es menos útil en la solicitud interactiva, pero limpia los archivos de script sin 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
fuente
0

Obviamente, hay muchas maneras de hacer esto: creo que me gusta más la respuesta sed de @ aragaer .

Aquí hay uno que usa puramente bash builtins y no necesita bifurcar ninguna utilidad externa:

for f in file{1..80}.dat; do
    { read && read && printf "%s\n" "$REPLY"; } < "$f"
done > output.dat
Trauma digital
fuente
0

Para un uso eficiente de awky seden las respuestas aquí en múltiples archivos, es mejor usar una nextfiledeclaración para omitir el procesamiento de líneas no deseadas awk.

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

y con sed, podemos salir al procesar el 3 rd línea y sedvamos a procesar el siguiente archivo.

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