J'ai un énorme fichier journal et je veux grep la première occurrence d'un modèle, puis trouver un autre modèle juste après cette occurrence.
Par exemple:
123
XXY
214
ABC
182
558
ABC
856
ABC
Dans mon exemple, je voudrais trouver 182
puis trouver la prochaine occurrence deABC
La première occurrence est simple:
grep -n -m1 "182" /var/log/file
Cela produit:
5:182
Comment trouver la prochaine occurrence d'ABC?
Mon idée était de dire grep
de sauter les premières n
lignes (dans l'exemple ci-dessus n=5
), sur la base du numéro de ligne de 182. Mais comment faire?
grep
est utilisée? Je ne pense pas que cela puisse être fait avecgrep
mais ce serait facile avecawk
oused
(seul ou en combinaison avecgrep
).grep
n'est pas requis. Je ne suis pas encore familier avecsed
ouawk
. Si vous avez une bonne solution, laissez-moi l'entendre! :) @don_crissti seule la première ligne doit être imprimée. Je me fiche des autres événements.Réponses:
Avec,
sed
vous pouvez utiliser une plage et uneq
entrée en une seule fois:De même avec GNU,
grep
vous pouvez diviser l'entrée entre deuxgrep
s:... qui imprime ...
... pour signifier que le premier a
grep
trouvé un-F
littéral de chaîne ixe, une-x
ligne entière 182 correspond à 5 lignes depuis le début de sa lecture, et le second a trouvé un ABC de type similaire correspondant à 2 lignes depuis le début de sa lecture - ou 2 lignes après le premiergrep
arrêt de lecture à la ligne 5.De
man grep
:J'ai utilisé un document ici pour une démonstration reproductible, mais vous devriez probablement le faire:
Il fonctionnera également avec d'autres constructions de commandes composées de shell comme:
la source
grep
's au lieu d'un;
... no-gogrep
partagent ici est effectivement un pipeline pour eux. Autre chose: j'ai essayé sans imprimer la ligne de marqueur maissed '//,/^ABC$/!d;/^ABC$/!d;q'
jette une étrange erreur. Que fait//
-il?sed
chose - je l'ai juste écrite très rapidement.sed
chose fonctionne - vous venez de laisser de côté la référence. Danssed
vous pouvez vous référer à/address/
nouveau au dernier avec une//
adresse vide . Il en va de/^182$/command;//,/next_address/
même/^182$/command;/^182$/,/next_address/
. Votre erreur n'était probablement pas une expression régulière précédente si vous utilisiez un GNUsed
. Soit dit en passant, le tuyau lseek peut être manipulé par indirection via les/dev/fd/[num]
liens sur les systèmes Linux - mais si vous ne faites pas très attention à bien gérer les tampons (comme avecdd
), c'est généralement une bataille perdue.Utiliser
grep
avec des expressions régulières compatibles Perl (pcregrep
):L'option
-M
permet au modèle de correspondre à plusieurs lignes et\K
n'inclut pas le modèle correspondant (jusqu'à ce point) dans la sortie. Vous pouvez supprimer\K
si vous souhaitez avoir la région entière en conséquence.la source
la source
awk '/^182$/{z=1;next} z&&/^ABC$/{print NR":"$0;exit}' file
- ou vous pouvez écrire au moins unegetline()
boucle explicite qui est généralement plus maladroite, ou être intelligent (?) en utilisant une plage presque similaire à @ JRFerguson perl:awk '!x&&/^182$/,/^ABC$/ {x=NR":"$0} END{print x}
Une variante Perl que vous pourriez utiliser est:
... qui imprime des lignes dans la plage correspondante.
Si votre fichier contient plusieurs plages correspondantes, vous pouvez limiter la sortie à la première plage uniquement en remplaçant le
/
délimiteur par?
la source
Rester avec juste
grep
et ajoutertail
&cut
, vous pourriez ...grep pour le numéro de ligne de la première correspondance de
182
:Utilisez cela pour grep pour tous les
ABC
's seulement après la première ligne correspondante ci-dessus, en utilisanttail
' s-n +K
pour sortir après la Kème ligne. Tous ensemble:Ou ajoutez à
-m 1
nouveau pour ne trouver que la première correspondanceABC
Références:
man
pages/programming/6958841/use-grep-to-report-back-only-line-numbers
la source
Une autre variante est la suivante:
Le drapeau -An salue n lignes après le match et 99999 est juste pour être sûr que nous ne manquons de rien. Les fichiers plus gros devraient avoir plus de lignes (vérifiez avec "wc -l").
la source
L'opérateur de plage
,
peut être utilisé ici:L'opérateur de plage
..
en tandem avec l' opérateur de correspondance uniquem??
peut être utilisé ici dansPerl
la source