extraer de línea en línea y luego guardar en un archivo separado

extraer de línea en línea y luego guardar en un archivo separado

Probé suerte con grepy sedpero de alguna manera no logro hacerlo bien.

Tengo un archivo de registro que tiene un tamaño de aproximadamente 8 GB. Necesito analizar un período de 15 minutos de actividad sospechosa. Localicé la parte del archivo de registro que necesito ver y estoy intentando extraer esas líneas y guardarlas en un archivo separado. ¿Cómo haría eso en una máquina CentOS normal?

Mi último intento fue este pero no funcionó. Estoy perdido cuando se trata de sedese tipo de comandos.

sed -n '2762818,2853648w /var/log/output.txt' /var/log/logfile

Respuesta1

sed -n '2762818,2853648p' /var/log/logfile > /var/log/output.txt

pes para imprimir

Respuesta2

Probablemente la mejor manera de hacerlo es con la redirección de shell, como otros han mencionado. sedsin embargo, si bien es un favorito personal, probablemente no lo hará de manera más eficiente que lo hará head, que está diseñado para capturar solo una cantidad determinada de líneas de un archivo.

Hay otras respuestas en este sitio que demuestran de manera demostrable que los archivos grandes head -n[num] | tail -n[num]tendrán un rendimiento superior seden todo momento, pero probablemente incluso más rápido que eso es evitar la tubería por completo.

Creé un archivo como:

echo | dd cbs=5000000 conv=block | tr \  \\n >/tmp/5mil_lines

Y lo repasé:

{ head -n "$((ignore=2762817))" >&2
  head -n "$((2853648-ignore))" 
} </tmp/5mil_lines 2>/dev/null  |
sed -n '1p;$p'                

Solo usé sedallí para tomar solo la primera y la última línea para mostrarles...

2762818
2853648

Esto funciona porque cuando agrupa comandos { ... ; }y redirige la entrada para el grupo, ... ; } <inputtodos compartirán la misma entrada. La mayoría de los comandos agotarán todo el archivo mientras lo leen, por lo que en un { cmd1 ; cmd2; } <infilecaso generalmente cmd1se lee desde el principio del archivo hasta el final y cmd2no queda nada.

head, sin embargo, siempre buscará sólo hasta donde se le indique en su archivo, y así en un...

{ head -n [num] >/dev/null
  head -n [num]
} <infile 

... caso el primero busca [num]y vuelca su salida /dev/nully el segundo se deja para comenzar su lectura donde lo dejó el primero.

Tu puedes hacer...

{ head -n "$((ignore=2762817))" >/dev/null
  head -n "$((2853648-ignore))" >/path/to/outfile
} <infile

Esta construcción también funciona con otros tipos de comandos compuestos. Por ejemplo:

set "$((n=2762817))" "$((2853648-n))"
for n do head "-n$n" >&"$#"; shift
done <5mil_lines 2>/dev/null | 
sed -n '1p;$p'

...que imprime...

2762818
2853648

Pero también podría funcionar así:

d=$(((  n=$(wc -l </tmp/5mil_lines))/43 ))      &&
until   [ "$(((n-=d)>=(!(s=143-n/d))))" -eq 0 ] &&
        head "-n$d" >>"/tmp/${s#1}.split"
do      head "-n$d" > "/tmp/${s#1}.split"       || ! break
done    </tmp/5mil_lines

Arriba del shell inicialmente establece las variables $ny $den ...

  • $n
    • El recuento de líneas según lo informado por wcmi archivo de prueba./tmp/5mil_lines
  • $d
    • El cociente de $n/43donde 43 es simplemente algún divisor seleccionado arbitrariamente.

Luego repite untillo que ha disminuido $na $dun valor less $d. Mientras lo hace, guarda su recuento dividido $sy usa ese valor en el bucle para incrementar el >archivo de salida nombrado llamado /tmp/[num].split. El resultado es que lee un número igual de \ncampos delimitados por ewline en su archivo de entrada en un nuevo archivo de salida para cada iteración, dividiéndolo igualmente 43 veces a lo largo del ciclo. Lo administra sin tener que leer su archivo interno más de 2 veces: la primera vez es cuando wccuenta sus líneas y durante el resto de la operación solo lee tantas líneas como escribe en el archivo externo cada vez.

Después de ejecutarlo verifiqué mis resultados como...

tail -n1 /tmp/*split | grep .

PRODUCCIÓN:

==> /tmp/01.split <==
116279  
==> /tmp/02.split <==
232558  
==> /tmp/03.split <==
348837  
==> /tmp/04.split <==
465116  
==> /tmp/05.split <==
581395  
==> /tmp/06.split <==
697674  
==> /tmp/07.split <==
813953  
==> /tmp/08.split <==
930232  
==> /tmp/09.split <==
1046511 
==> /tmp/10.split <==
1162790 
==> /tmp/11.split <==
1279069 
==> /tmp/12.split <==
1395348 
==> /tmp/13.split <==
1511627 
==> /tmp/14.split <==
1627906 
==> /tmp/15.split <==
1744185 
==> /tmp/16.split <==
1860464 
==> /tmp/17.split <==
1976743 
==> /tmp/18.split <==
2093022 
==> /tmp/19.split <==
2209301 
==> /tmp/20.split <==
2325580 
==> /tmp/21.split <==
2441859 
==> /tmp/22.split <==
2558138 
==> /tmp/23.split <==
2674417 
==> /tmp/24.split <==
2790696 
==> /tmp/25.split <==
2906975 
==> /tmp/26.split <==
3023254 
==> /tmp/27.split <==
3139533 
==> /tmp/28.split <==
3255812 
==> /tmp/29.split <==
3372091 
==> /tmp/30.split <==
3488370 
==> /tmp/31.split <==
3604649 
==> /tmp/32.split <==
3720928 
==> /tmp/33.split <==
3837207 
==> /tmp/34.split <==
3953486 
==> /tmp/35.split <==
4069765 
==> /tmp/36.split <==
4186044 
==> /tmp/37.split <==
4302323 
==> /tmp/38.split <==
4418602 
==> /tmp/39.split <==
4534881 
==> /tmp/40.split <==
4651160 
==> /tmp/41.split <==
4767439 
==> /tmp/42.split <==
4883718 
==> /tmp/43.split <==
5000000 

Respuesta3

Probablemente puedas lograr esto con la ayuda de headlas tailcombinaciones de comandos que se muestran a continuación.

head -n{to_line_number} logfile | tail -n+{from_line_number} > newfile

Reemplace from_line_numbery to_line_numbercon los números de línea que desee.

Pruebas

cat logfile
This is first line.
second
Third
fourth
fifth
sixth
seventh
eighth
ninth
tenth

##I use the command as below. I extract from 4th line to 10th line. 

head -n10 logfile | tail -n+4 > newfile
fourth
fifth
sixth
seventh
eighth
ninth
tenth

información relacionada