Mire a través de un archivo e imprima texto desde líneas específicas

8

Tengo un archivo con datos que guardo. Ahora me gustaría imprimir mis resultados en un nuevo archivo.

Por ejemplo, tomemos este ejemplo randomlog.log:

Link encap:Ethernet HWaddr 08:00:00:00:00:67
inet addr:10.10.10.10 Bcast:10.10.10.10 Mask:255.255.255.0
inet6 addr: fe80::casf:sdfg:23ra:dg12/64 Scope:Link

¿Cómo puedo tomar solo datos del 12 ° al 20 ° carácter de la primera línea y luego del 4 ° al 8 ° carácter de la 3 ° línea? La salida se vería así:

Ethernet
t6 ad

es posible? Quiero establecer la línea y desde la posición a esta posición.

Insanebench420
fuente

Respuestas:

9

Aquí hay un sedenfoque:

$ sed -nE '1s/.{11}(.{8}).*/\1/p; 3s/.{3}(.{4}).*/\1/p' file  
Ethernet
t6 a

Explicación

El -nsuprime la salida normal (normal es imprimir cada línea de entrada) de forma que sólo se imprime cuando se le dijo a. El -Epermite expresiones regulares extendidas.

El sedscript tiene dos comandos, ambos utilizando el operador de sustitución ( s/original/replacement/). El 1s/.{11}(.{8}).*/\1/psolo se ejecutará en la primera línea (eso es lo que 1shace), y coincidirá con los primeros 11 caracteres de la línea ( .{11}), luego capturará los siguientes 8 ( (.{8}), los paréntesis son un "grupo de captura") y luego todo lo demás hasta El final de la línea ( .*). Todo esto se reemplaza con lo que haya en el grupo de captura ( \1; si hubiera un segundo grupo de captura, sería \2etc.). Finalmente, pal final ( s/foo/bar/p) hace que la línea se imprima después de que se ha realizado la sustitución. Esto da como resultado que solo se muestren los 8 caracteres de destino.

El segundo comando es la misma idea general, excepto que solo se ejecutará en la tercera línea ( 3s) y mantendrá los 4 caracteres a partir de la cuarta.


También podría hacer lo mismo con perl:

$ perl -ne 'if($.==1){s/.{11}(.{8}).*/\1/}
            elsif($.==3){s/.{3}(.{4}).*/\1/}
            else{next}; print; ' file 
Ethernet
t6 a

Explicación

El -nemedio "lee el archivo de entrada línea por línea y aplica la secuencia de comandos dada por -ecada línea. La secuencia de comandos es la misma idea básica que antes. La $.variable contiene el número de línea actual, por lo que verificamos si el número de línea es 1o 3y, si entonces, ejecute la sustitución, de lo contrario, omita. Por lo tanto print, solo se ejecutará para esas dos líneas, ya que todas las demás se omitirán.


Por supuesto, esto es Perl, entonces TIMTOWTDI :

$ perl -F"" -lane '$. == 1 && print @F[11..19]; $.==3 && print @F[3..6]' file 
Ethernet 
t6 a

Explicación

Aquí, los -amedios "dividen cada línea de entrada en el carácter dado por -Fy guardan como la matriz @F. Dado que el carácter dado está vacío, esto guardará cada carácter de la línea de entrada como un elemento @F. Luego, imprimimos los elementos 11-19 ( las matrices comienzan a contar en 0) para la primera línea y 3-7 para la tercera.

terdon
fuente
1

enfoque awk:

$ awk 'NR==1{print substr($0,12,8)};NR==3{print substr($0,4,4)}' input.txt  
Ethernet
t6 a

Usos NRpara determinar el número de línea (en terminología awk - registro) y, en consecuencia, imprimir la subcadena de la línea. substr()la función está en formato

substr(string,starting position,how much offset) 

Pitón

$ python -c 'import sys                                                                                                                                                
> for index,line in enumerate(sys.stdin,1):                                                                                                                            
>     if index == 1:
>          print line[11:19]
>     if index == 3:
>          print line[3:7]' < input.txt
Ethernet
t6 a

Esto utiliza el <operador de shell para redirigir la secuencia de entrada al proceso de Python desde el archivo de entrada. Tenga en cuenta que las cadenas en Python están indexadas en 0, por lo tanto, debe cambiar los números de caracteres deseados por 1.

forma de concha portátil

Esto funciona en ksh, dash, bash. Se basa solo en utilidades de shell, nada externo.

#!/bin/sh

rsubstr(){
    i=0;
    while [ $i -lt  $2 ];
    do
        rmcount="${rmcount}?"
        i=$(($i+1))
    done;
    echo "${1#$rmcount}"
}

lsubstr(){
    printf "%.${2}s\n" "$1"
}

line_handler(){
    case $2 in
        1) lsubstr "$(rsubstr "$1" 11)" 8 ;;
        3) lsubstr "$(rsubstr "$1" 3)" 5 ;;
    esac
}

readlines(){
    line_count=1
    while IFS= read -r line;
    do
        line_handler "$line" "$line_count"
        line_count=$(($line_count+1))
    done < $1
}

readlines "$1"

Y funciona así:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad
Sergiy Kolodyazhnyy
fuente