awk-Ansatz:

awk-Ansatz:

Ich habe eine Datei mit Daten, die ich speichere. Nun möchte ich meine Ergebnisse in eine neue Datei ausdrucken.

Nehmen wir zum Beispiel dieses 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

Wie kann ich nur Daten vom 12. bis zum 20. Zeichen der ersten Zeile und dann vom 4. bis zum 8. Zeichen der 3. Zeile übernehmen? Die Ausgabe würde ungefähr so ​​aussehen:

Ethernet
t6 ad

Ist das möglich? Ich möchte die Linie und die Von-Position zu dieser Position setzen.

Antwort1

Hier ist ein sedAnsatz:

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

Erläuterung

Das -nunterdrückt die normale Ausgabe (normalerweise wird jede Eingabezeile gedruckt), so dass nur gedruckt wird, wenn dies angefordert wird. Das -Eaktiviert erweiterte reguläre Ausdrücke.

Das sedSkript hat zwei Befehle, die beide den Substitutionsoperator ( s/original/replacement/) verwenden. Der 1s/.{11}(.{8}).*/\1/pwird nur in der 1. Zeile ausgeführt (das macht der 1s) und gleicht die ersten 11 Zeichen der Zeile ab ( .{11}), dannerfasstdie nächsten 8 ( (.{8}), die Klammern sind eine „Erfassungsgruppe“) und dann alles andere bis zum Ende der Zeile ( .*). All dies wird durch das ersetzt, was in der Erfassungsgruppe war ( \1; wenn es eine zweite Erfassungsgruppe gäbe, wäre es \2usw.). Schließlich bewirkt das pam Ende ( s/foo/bar/p), dass die Zeile gedruckt wird, nachdem die Ersetzung vorgenommen wurde. Dies führt dazu, dass nur die Ziel-8-Zeichen ausgegeben werden.

Der zweite Befehl basiert im Wesentlichen auf der gleichen Idee, außer dass er nur in der 3. Zeile ( ) ausgeführt wird 3sund die 4 Zeichen ab der 4. Zeile beibehält.


Sie können dasselbe auch mit tun perl:

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

Erläuterung

Das -nebedeutet „liest die Eingabedatei Zeile für Zeile und wendet das von angegebene Skript -eauf jede Zeile an.“ Das Skript hat dieselbe Grundidee wie zuvor. Die $.Variable enthält die aktuelle Zeilennummer, daher prüfen wir, ob die Zeilennummer entweder 1oder ist 3, und führen in diesem Fall die Ersetzung aus, andernfalls überspringen wir. Daher printwird das nur für diese beiden Zeilen ausgeführt, da alle anderen übersprungen werden.


Natürlich ist das Perl, alsoZEITSCHRIFT:

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

Erläuterung

Hier -abedeutet „teile jede Eingabezeile in das durch angegebene Zeichen auf -Fund speichere es als Array“ @F. Da das angegebene Zeichen leer ist, wird hierdurch jedes Zeichen der Eingabezeile als Element in gespeichert @F. Dann drucken wir die Elemente 11-19 (Arrays beginnen bei zu zählen 0) für die 1. Zeile und 3-7 für die 3.

Antwort2

awk-Ansatz:

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

Wird verwendet NR, um die Zeilennummer (in der AWK-Terminologie - Datensatznummer) zu bestimmen und dementsprechend einen Teilstring der Zeile zu drucken. substr()Die Funktion hat das Format

substr(string,starting position,how much offset) 

Python

$ 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

Dabei wird <ein Shell-Operator verwendet, um den Eingabestrom von der Eingabedatei zum Python-Prozess umzuleiten. Beachten Sie, dass Zeichenfolgen in Python 0-indiziert sind, Sie müssen daher die gewünschten Zeichenzahlen alle um 1 verschieben.

tragbare Shell-Methode

Dies funktioniert in ksh, dash, bash. Basiert nur auf Shell-Dienstprogrammen, nichts Externem.

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

Und so funktioniert es:

$ ./get_line_substrings.sh input.txt                                                                                                                                   
Ethernet
t6 ad

verwandte Informationen