Entrada:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Rendimiento esperado:
1
2
3
4
Entonces, necesito tener solo el 1er, 5to, 9no, 13er valor del archivo en el archivo de salida. ¿Como hacer esto?
Entrada:
1
hgh
h2b
h4h
2
ok
koko
lkopk
3
uh
ju
nfjvn
4
Rendimiento esperado:
1
2
3
4
Entonces, necesito tener solo el 1er, 5to, 9no, 13er valor del archivo en el archivo de salida. ¿Como hacer esto?
Respuestas:
Usando AWK:
awk '!((NR - 1) % 4)' input > output
Descubrir cómo funciona esto se deja como un ejercicio para el lector.
NR % 4 == 1
Sería más legible en mi opinión.
Usando split
(GNU coreutils):
split -nr/1/4 input > output
-n
generar CHUNKS
archivos de saliday CHUNKS
como
r/K/N
use la distribución round robin y solo envíe Kth of N a stdout sin dividir líneas / registrosCon GNU sed
:
sed '1~4!d' < input > output
Con estándar sed
:
sed -n 'p;n;n;n' < input > output
Con 1
y 4
en $n
y $i
variables:
sed "$n~$i!d" # GNU only
awk -v n="$n" -v i="$i" 'NR >= n && (NR % i) == (n % i)'
Versión de Python, solo por diversión:
with open('input.txt') as f:
for i, line in enumerate(f.readlines()):
if i%4 == 0:
print(line.strip())
enumerate(f)
debería poder hacer el trabajo mientras consume menos memoria
readlines
(por lo tanto, arrastrando todo el archivo a la memoria), puede usarlo f.readlines()[::4]
para obtener cada cuarta línea. Entonces puedes usar print(''.join(f.readlines()[::4]))
.
POSIX sed
: este método utiliza el posixly sed y, por lo tanto, se puede ejecutar en todas partes, o al menos aquellos seds que respetan posixly.
$ sed -ne '
/\n/!{
H;s/.*//;x
}
:loop
$bdone
N;s/\n/&/4
tdone
bloop
:done
s/.//;P
' input.file
Otra es una generación programática de código sed para fines de escalabilidad:
$ code=$(yes n | head -n 4 | paste -sd\; | sed s/n/p/)
$ sed -ne "$code" input.file
Perl
: rellenamos la matriz A hasta que tenga un tamaño de 4. Luego imprimimos su primer elemento y también limpiamos la matriz.
$ perl -pe '
$A[@A] = @A ? <> : $_ while @A < 4;
$_ = (splice @A)[0];
' input.file
Llame con scriptname filename skip
(4 en su caso) Funciona tirando iter
líneas desde la parte superior del archivo y luego solo genera la última. A continuación, incrementa iter
por skips
y se repite mientras el valor de iter
no ha excedido el lines
en file
.
#!/bin/bash
file="$1"
lines=`wc -l < "$file"`
skips="$2" || "4"
iter=1
while [ "$iter" -le "$lines" ]; do
head "$file" -n $iter | tail -n 1
iter=$(( $iter + $skips ))
done
Golpe puro:
mapfile -t lines < input
for (( i=0; i < ${#lines[@]}; i+=4 ))
do printf "%s\n" "${lines[$i]}"
done
mapfile es un archivo incorporado en Bash 4 que lee la entrada estándar en una matriz, aquí llamada lines
, con una línea por entrada. La -t
opción elimina las nuevas líneas finales.
Si desea imprimir cada cuarta línea a partir de la línea 4, puede hacerlo en un comando utilizando mapfile
la opción de devolución de llamada -C
, que ejecuta el código proporcionado cada tantas líneas, con el intervalo dado por -c
. El índice de matriz actual y la siguiente línea a asignar se dan al código como argumentos.
mapfile -t -c4 -C 'printf "%.0s%s\n"' < input
Esto usa el printf
incorporado; el código de formato %.0s
suprime el primer argumento (el índice), por lo que solo se imprime la línea.
Podría usar el mismo comando para imprimir cada cuarta línea a partir de la línea 1, 2 o 3, pero tendría que anteponer 3, 2 o 1 líneas input
antes de alimentarlo mapfile
, lo que creo que es más problemático de lo que vale la pena. .
Esto también funciona:
mapfile -t lines < input
printf "%s%.0s%.0s%.0s\n" "${lines[@]}"
Aquí, printf
consume cuatro entradas de la matriz lines
a la vez, solo imprime la primera y omite las otras tres con %.0s
. No me gusta esto, ya que tienes que manipular manualmente la cadena de formato para diferentes intervalos o puntos de partida.
sed -n '1~4p'