Cerca un file e stampa il testo da righe specifiche


8

Ho un file con i dati che ho salvato. Ora vorrei stampare i miei risultati in un nuovo file.

Ad esempio, prendiamo questo esempio 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

Come posso prendere solo i dati dal 12 ° al 20 ° carattere della prima riga e quindi dal 4 ° all'8 ° carattere della 3 ° riga? L'output sarebbe simile al seguente:

Ethernet
t6 ad

È possibile? Voglio impostare la linea e da posizione a questa posizione.

Risposte:


9

Ecco un sedapproccio:

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

Spiegazione

L' -nuscita normale sopprime (normale è quello di stampare ogni linea di ingresso) in modo che la stampa solo quando ha detto di. L' -Eabilita le espressioni regolari estese.

Lo sedscript ha due comandi, entrambi utilizzano l'operatore di sostituzione ( s/original/replacement/). L' 1s/.{11}(.{8}).*/\1/pverrà eseguito solo sulla linea 1 (che è quello che la 1sfa), e corrisponderà al primo 11 caratteri della linea ( .{11}), quindi cattura i prossimi 8 ( (.{8})le parentesi sono un "gruppo di cattura") e poi tutto il resto fino a quando la fine della linea ( .*). Tutto questo viene sostituito con qualsiasi cosa fosse nel gruppo di acquisizione ( \1; se ci fosse un secondo gruppo di acquisizione, sarebbe \2ecc.). Infine, palla fine ( s/foo/bar/p) fa sì che la riga venga stampata dopo aver effettuato la sostituzione. Ciò si traduce in un output di soli 8 caratteri target.

Il secondo comando è la stessa idea generale, tranne per il fatto che verrà eseguito solo sulla 3a riga ( 3s) e manterrà i 4 caratteri a partire dalla 4a.


Puoi anche fare la stessa cosa con perl:

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

Spiegazione

Il -nemezzo "legge il file di input riga per riga e applica lo script fornito da -eciascuna riga. Lo script è la stessa idea di base di prima. La $.variabile contiene il numero di riga corrente, quindi controlliamo se il numero di riga è o 1o 3e, se quindi, esegui la sostituzione, altrimenti salta. Pertanto printverrà eseguito solo per quelle due righe poiché tutte le altre verranno ignorate.


Certo, questo è Perl, quindi TIMTOWTDI :

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

Spiegazione

Qui, i -amezzi "suddividono ogni riga di input sul carattere dato da -Fe salvano come matrice @F. Poiché il carattere fornito è vuoto, ciò salverà ogni carattere della riga di input come elemento in @F. Quindi, stampiamo gli elementi 11-19 ( le matrici iniziano a contare da 0) per la 1a riga e 3-7 per la 3a.


1

approccio awk:

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

Utilizza NRper determinare il numero di riga (nella terminologia awk - record) e, di conseguenza, stampare la sottostringa della linea. substr()la funzione è in formato

substr(string,starting position,how much offset) 

Pitone

$ 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

Questo utilizza l' <operatore shell per reindirizzare il flusso di input al processo python dal file di input. Nota che le stringhe in Python sono indicizzate a 0, quindi devi spostare i numeri di caratteri desiderati tutti di 1.

modo shell portatile

Questo funziona in ksh, dash, bash. Si basa solo su utilità di shell, niente di esterno.

#!/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"

E funziona così:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.