web-dev-qa-db-fra.com

Comment "grep" des plages de lignes spécifiques d'un fichier

Il y a souvent des fois que je grep -n fichier whatev pour trouver ce que je cherche. Disons que la sortie est

1234: whatev 1
5555: whatev 2
6643: whatev 3

Si je veux ensuite extraire les lignes entre 1234 et 5555, existe-t-il un outil pour le faire? Pour les fichiers statiques, j'ai un script qui fait wc -l du fichier, puis fait le calcul pour le diviser avec tail & head mais cela ne fonctionne pas si bien avec les fichiers journaux qui sont constamment écrits.

48
Mike

Essayez d'utiliser sed comme mentionné sur http://linuxcommando.blogspot.com/2008/03/using-sed-to-extract-lines-in-text-file.html . Par exemple, utilisez

sed '2,4!d' somefile.txt

pour imprimer de la deuxième ligne à la quatrième ligne de somefile.txt. (Et n'oubliez pas de vérifier http://www.grymoire.com/Unix/Sed.html , sed est un merveilleux outil.)

76
Scorchio

La commande suivante fera ce que vous avez demandé "extraire les lignes entre 1234 et 5555" dans someFile.

sed -n '1234,5555p' someFile

23
javaPlease42

Si je comprends bien, vous voulez trouver un modèle entre deux numéros de ligne. L'awk one-liner pourrait être

awk '/whatev/ && NR >= 1234 && NR <= 5555' file

Vous n'avez pas besoin d'exécuter grep suivi de sed.

Perl one-liner:

Perl -ne 'if (/whatev/ && $. >= 1234 && $. <= 5555') {print}' file
5
Mark Lakata

Les numéros de ligne sont OK si vous pouvez garantir la position de ce que vous voulez. Au fil des ans, ma saveur préférée a été quelque chose comme ceci:

sed "/First Line of Text/,/Last Line of Text/d" filename

qui supprime toutes les lignes de la première ligne correspondante à la dernière correspondance, y compris ces lignes.

Utilisez sed - n avec "p" au lieu de "d" pour imprimer ces lignes à la place. Beaucoup plus utile pour moi, car je ne sais généralement pas où sont ces lignes.

2
psbrightly

Mettez-le dans un fichier et rendez-le exécutable:

#!/bin/bash
start=`grep -n $1 < $3 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[0]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find start pattern!" 1>&2
    exit 1
fi
stop=`tail -n +$start < $3 | grep -n $2 | head -n1 | cut -d: -f1; exit ${PIPESTATUS[1]}`
if [ ${PIPESTATUS[0]} -ne 0 ]; then
    echo "couldn't find end pattern!" 1>&2
    exit 1
fi

stop=$(( $stop + $start - 1))

sed "$start,$stop!d" < $3

Exécutez le fichier avec des arguments (REMARQUE: le script ne gère pas les espaces dans les arguments!):

  1. Démarrage du modèle grep
  2. Arrêt du motif grep
  3. Chemin du fichier

Pour utiliser avec votre exemple, utilisez des arguments: 1234 5555 myfile.txt

Comprend des lignes avec un motif de démarrage et d'arrêt.

0
Janus Troelsen

Si vous voulez des lignes au lieu de plages de lignes, vous pouvez le faire avec Perl: par exemple. si vous voulez obtenir les lignes 1, 3 et 5 d'un fichier, dites/etc/passwd:

Perl -e 'while(<>){if(++$l~~[1,3,5]){print}}' < /etc/passwd
0
dagelf