grep un fichier, mais montre plusieurs lignes environnantes?

3421

Je voudrais greppour une chaîne, mais aussi montrer les cinq lignes précédentes et les cinq lignes suivantes ainsi que la ligne correspondante. Comment pourrais-je faire cela?

Mark Harrison
la source
3
Je garde une copie du script perl de Brendan Gregg à cet effet. Fonctionne bien.
Ethan Post
6
Pour une solution qui fonctionne sur Solaris, consultez ce lien .
jahroy
107
man grep | grep -C 1 context:)
StvnW
20
man grep | grep -C 1 "\-C";)
Anders B
9
@StvnW ... Je ne sais pas s'il faut appeler cette méta (dans un contexte plus général, plutôt que SO), ni comment l'appeler. Vous avez répondu à la question en montrant comment utiliser la réponse pour trouver la réponse.
bballdave025

Réponses:

4540

Pour BSD ou GNU, grep vous pouvez utiliser -B numpour définir le nombre de lignes avant la correspondance et -A numle nombre de lignes après la correspondance.

grep -B 3 -A 2 foo README.txt

Si vous voulez le même nombre de lignes avant et après, vous pouvez utiliser -C num.

grep -C 3 foo README.txt

Cela montrera 3 lignes avant et 3 lignes après.

Pat Notz
la source
56
C'est bien mais malheureusement le grep Solaris ne le supporte pas. Voir ce lien pour solaris: unix.com/solaris/33533-grep-display-few-lines-before-after.html
2011
9
Ok, mais que faire si vous voulez afficher toutes les lignes de sortie après le match? grep -A0 et grep -A-1 ne le coupent pas ...
g33kz0r
2
ne fonctionne pas pour moi pour une raison quelconque, bien que mentionné dans mes pages de manuel.
Hayri Uğur Koltuk
2
Si vous êtes env HP-UX, aucune des versions grep ne fonctionnera comme dans Solaris. A pu utiliser le lien Solaris mais remplacer nawk par awk dans ce lien.
zkarthik
6
-n est pour les numéros de ligne, mais pour certaines versions de grep -n # affichera # lignes environnantes (comme -c) avec des numéros de ligne. C'est un raccourci utile qui est mon choix lorsque j'ai besoin de contexte.
Anthony DiSanti
607

-Aet -Bfonctionnera, comme le fera -C n(pour les nlignes de contexte), ou tout simplement -n(pour les nlignes de contexte ... tant que n est 1 à 9).

Stu
la source
J'ai essayé le -nformat et j'ai découvert qu'il ne fonctionnait que jusqu'à 9. Car 15il renvoie 5 lignes
Deepak Mahakale
8
@DeepakMahakale Ceci est probablement lié à la façon dont les arguments / options de ligne de commande sont généralement analysés par les programmes POSIX. Le spécificateur d'option est un seul caractère (tel que -A, -Bou -C). Habituellement, le spécificateur d'option est suivi d'une valeur ( -o a.outpour spécifier le fichier de sortie dans GCC), mais il peut également fonctionner comme un simple commutateur / indicateur ( -gpour activer les informations de débogage dans GCC). Cependant, les espaces entre les options sont facultatifs, donc pour les options sans valeur, il est possible de les fusionner ( -ABC), ce qui signifie que cela -15est interprété -1 -5(deux options distinctes) et le -5remplace le -1.
natiiix
1
-5 est plus rapide que les deux -A 5 -B 5. Ceux-ci ne sont pas destinés à être utilisés ensemble. Il est plus propre aux autres lecteurs du script si vous choisissez -A ou -B ou -C sur -9.
Eric Aldinger
77

ack fonctionne avec des arguments similaires à grep et accepte -C. Mais il est généralement préférable de rechercher dans le code.

elmarco
la source
5
ack prend également en charge -A -B.
Shuo
Ack est meilleur que grep à bien des égards. C'est plus rapide avec une syntaxe plus simple.
chim
1
grep a l'avantage d'être installé par défaut sur de nombreux systèmes.
Marc Z
1
@MarcZ: Certes, grep est plus susceptible d'être installé par défaut qu'ack, mais ack est un script portable et autonome. Il n'est pas nécessaire de le compiler ou de l'installer dans un répertoire système tel que / usr / bin /. Une fois qu'il est téléchargé et placé dans un répertoire répertorié dans $ PATH (et son ensemble de bits d'autorisation eXecute), il devrait fonctionner immédiatement. (Aucun privilège sudo ou root n'est requis pour faire fonctionner ack.)
JL
Cette question est à propos grep, pas sûr de l'utiliser pour "faire de la publicité" ack(qui est un excellent outil, en effet) est une bonne idée ...
MonsieurDart
39
grep astring myfile -A 5 -B 5

Cela va grep "monfichier" pour "astring", et afficher 5 lignes avant et après chaque match

dbr
la source
19
"grep astring myfile -C 5" fera de même
Syed Siraj Uddin
20

J'utilise normalement

grep searchstring file -C n # n for number of lines of context up and down

De nombreux outils comme grep ont également de très bons fichiers man. Je me réfère souvent à la page de manuel de grep car il y a tellement de choses que vous pouvez faire avec.

man grep

De nombreux outils GNU ont également une page d'informations qui peut contenir des informations plus utiles en plus de la page de manuel.

info grep
Sam Merrell
la source
13

Utilisez grep

$ grep --help | grep -i context
Context control:
  -B, --before-context=NUM  print NUM lines of leading context
  -A, --after-context=NUM   print NUM lines of trailing context
  -C, --context=NUM         print NUM lines of output context
  -NUM                      same as --context=NUM
Chiel ten Brinke
la source
Vous n'avez pas lu la réponse acceptée? Vous venez de répéter ce qui a déjà été dit sur une question vieille de presque 10 ans ...
Yokai
7
Oh je suis désolé Yokai. Mais je ne lis rien sur l'accueil de la section d'aide de grep pour récupérer la réponse.
Chiel ten Brinke
1
@Yokai Outre ce que Chiel ten Brinke a dit, la réponse acceptée ne mentionne pas les options longues
user3738870
11

Recherchez «17655» dans «/some/file.txt» montrant le contexte de 10 lignes avant et après (en utilisant Awk), la sortie précédée du numéro de ligne suivi de deux points. Utilisez-le sur Solaris lorsque 'grep' ne prend pas en charge les options "- [ACB]".

awk '

/17655/ {
        for (i = (b + 1) % 10; i != b; i = (i + 1) % 10) {
                print before[i]
        }
        print (NR ":" ($0))
        a = 10
}

a-- > 0 {
        print (NR ":" ($0))
}

{
        before[b] = (NR ":" ($0))
        b = (b + 1) % 10
}' /some/file.txt;
Malcolm Boekhoff
la source
7

ripgrep

Si vous vous souciez des performances, utilisez ripgrepune syntaxe similaire à grep, par exemple

rg -C5 "pattern" .

-C, --context NUM- Afficher NUM lignes avant et après chaque match.

Il existe également des paramètres tels que -A/ --after-contextet -B/ --before-context.

L'outil est construit sur le moteur de regex de Rust, ce qui le rend très efficace sur les grandes données.

kenorb
la source
5

Voici la solution @Ygor enawk

awk 'c-->0;$0~s{if(b)for(c=b+1;c>1;c--)print r[(NR-c+1)%b];print;c=a}b{r[NR%b]=$0}' b=3 a=3 s="pattern" myfile

Remarque: remplacez aet bvariables par le nombre de lignes avant et après.

Il est particulièrement utile pour le système qui ne supporte pas de grep -A, -Bet les -Cparamètres.

kenorb
la source
4
$ grep thestring thefile -5

-5vous obtient des 5lignes au-dessus et au-dessous du match 'thestring' est équivalent à -C 5ou -A 5 -B 5.

JBone
la source
4

Grep a une option appelée Context Line Control, vous pouvez utiliser le --context, simplement,

| grep -C 5

ou

| grep -5

Devrait faire l'affaire

premier
la source
1

J'utilise pour faire de la manière compacte

grep -5 string file

C'est l'équivalent de

grep -A 5 -B 5 string file
franzisk
la source
0

Si vous recherchez souvent du code, AG le chercheur argent est beaucoup plus efficace (c'est-à-dire plus rapide) que grep.

Vous affichez les lignes de contexte en utilisant l'option -C.

Par exemple:

ag -C 3 "foo" myFile

line 1
line 2
line 3
line that has "foo"
line 5
line 6
line 7
Rose
la source