Parcourez un fichier et imprimez du texte à partir de lignes spécifiques

8

J'ai un fichier avec des données que j'enregistre. Maintenant, je voudrais imprimer mes résultats dans un nouveau fichier.

Par exemple, prenons cet exemple 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

Comment puis-je prendre uniquement des données du 12e au 20e caractère de la première ligne puis des 4e au 8e caractères de la 3e ligne? La sortie ressemblerait à ceci:

Ethernet
t6 ad

Est-ce possible? Je veux définir la ligne et de la position à cette position.

Insanebench420
la source

Réponses:

9

Voici une sedapproche:

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

Explication

Le -nsupprime la sortie normale (la normale consiste à imprimer chaque ligne d'entrée) de sorte qu'elle ne s'imprime que lorsque cela lui est demandé. Le -Epermet des expressions régulières étendues.

Le sedscript a deux commandes, toutes deux utilisant l'opérateur de substitution ( s/original/replacement/). Le 1s/.{11}(.{8}).*/\1/pne fonctionnera que sur la 1ère ligne (c'est ce que 1sfait), et correspondra aux 11 premiers caractères de la ligne ( .{11}), puis il capture les 8 suivants ( (.{8}), les parenthèses sont un "groupe de capture") et puis tout le reste jusqu'à ce que la fin de la ligne ( .*). Tout cela est remplacé par tout ce qui était dans le groupe de capture ( \1; s'il y avait un deuxième groupe de capture, ce serait \2etc.). Enfin, le pà la fin ( s/foo/bar/p) provoque l'impression de la ligne une fois la substitution effectuée. Cela se traduit uniquement par la sortie des 8 caractères cibles.

La deuxième commande est la même idée générale sauf qu'elle ne s'exécutera que sur la 3ème ligne ( 3s) et conservera les 4 caractères à partir de la 4ème.


Vous pouvez également faire la même chose avec perl:

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

Explication

Le -nemoyen "lit le fichier d'entrée ligne par ligne et applique le script donné par -eà chaque ligne. Le script est la même idée de base qu'auparavant. La $.variable contient le numéro de ligne actuel, donc nous vérifions si le numéro de ligne est soit 1ou 3et et, si exécutez la substitution, sinon sautez. Par conséquent, le printne sera exécuté que pour ces deux lignes car toutes les autres seront ignorées.


Bien sûr, c'est Perl, donc TIMTOWTDI :

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

Explication

Ici, le -amoyen "divise chaque ligne d'entrée sur le caractère donné par -Fet enregistre en tant que tableau @F. Puisque le caractère donné est vide, cela enregistrera chaque caractère de la ligne d'entrée en tant qu'élément dans @F. Ensuite, nous imprimons les éléments 11-19 ( les tableaux commencent à compter à 0) pour la 1ère ligne et 3-7 pour la 3ème.

terdon
la source
1

approche awk:

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

Utilise NRpour déterminer le numéro de ligne (en terminologie awk - enregistrement) et, par conséquent, imprimer la sous-chaîne de la ligne. substr()la fonction est au 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

Cela utilise l' <opérateur shell pour rediriger le flux d'entrée vers le processus python à partir du fichier d'entrée. Notez que les chaînes en python sont indexées 0, vous devez donc décaler vos numéros de caractères souhaités de 1.

façon coquille portable

Cela fonctionne ksh, dash, bash. Ne repose que sur des utilitaires shell, rien d'extérieur.

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

Et ça marche comme ça:

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