GNU/Linux >> Tutoriels Linux >  >> Linux

10 exemples pratiques de commandes Grep pour les développeurs

Récemment, j'ai commencé à travailler avec Asciidoctor.js et sur les projets Asciidoctor.js-pug et Asciidoctor-templates.js.

Il n'est pas toujours facile d'être immédiatement efficace lorsque l'on fouille pour la première fois dans une base de code contenant plusieurs milliers de lignes. Mais mon arme secrète pour trouver mon chemin à travers tant de lignes de code est le grep outil.

Je vais partager avec vous comment utiliser la commande grep sous Linux avec des exemples.

Exemples utiles réels des commandes grep sous Linux

Si vous regardez dans le man , vous verrez cette courte description pour le grep outil :"imprimer des lignes correspondant à un motif."

Cependant, ne vous laissez pas berner par une définition aussi humble :grep est l'un des outils les plus utiles de la boîte à outils Unix et il existe d'innombrables occasions de l'utiliser dès que vous travaillez avec des fichiers texte.

Il est toujours préférable d'avoir des exemples concrets pour apprendre comment les choses fonctionnent. Donc, j'utiliserai l'arbre source Asciidoctor.js pour illustrer certains des grep capacités.

Vous pouvez télécharger cette arborescence source à partir de GitHub, et si vous le souhaitez, vous pouvez même consulter le même ensemble de modifications que j'ai utilisé lors de la rédaction de cet article. Cela vous assurera d'obtenir des résultats parfaitement identiques à ceux décrits dans la suite de cet article :

git clone https://github.com/asciidoctor/asciidoctor.js
cd asciidoctor.js
git checkout v1.5.6-rc.1

1. Trouver toutes les occurrences d'une chaîne (utilisation de base)

Asciidoctor.js prend en charge le moteur JavaScript Nashorn pour la plate-forme Java. Je ne connais pas Nashorn, je pourrais donc en profiter pour en savoir plus en explorant les parties du projet faisant référence à ce moteur JavaScript.

Comme point de départ, j'ai vérifié s'il y avait des paramètres liés à Nashorn dans le package.json fichier décrivant les dépendances du projet :

[email protected]:~$ grep nashorn package.json
    "test": "node npm/test/builder.js && node npm/test/unsupported-features.js && node npm/test/jasmine-browser.js && node npm/test/jasmine-browser-min.js && node npm/test/jasmine-node.js && node npm/test/jasmine-webpack.js && npm run test:karmaBrowserify && npm run test:karmaRequirejs && node npm/test/nashorn.js",

Oui, apparemment il y avait des tests spécifiques à Nashorn. Alors, examinons cela un peu plus.

2. Recherche insensible à la casse dans un ensemble de fichiers

Maintenant, je veux regarder de plus près les fichiers du ./npm/test/ répertoire mentionnant explicitement Nashorn.

Une recherche insensible à la casse (-i option) est probablement mieux ici car j'ai besoin de trouver les deux références à nashorn et Nashorn (ou toute autre combinaison de caractères majuscules et minuscules) :

[email protected]:~$ grep -i nashorn npm/test/*.js
npm/test/nashorn.js:const nashornModule = require('../module/nashorn');
npm/test/nashorn.js:log.task('Nashorn');
npm/test/nashorn.js:nashornModule.nashornRun('jdk1.8.0');

En effet, l'insensibilité à la casse était utile ici. Sinon, j'aurais raté le require('../module/nashorn') déclaration. Je devrais sans doute examiner ce dossier plus en détail plus tard.

3. Trouver tous les fichiers non correspondants

Au fait, y a-t-il des fichiers non spécifiques à Nashorm dans le npm/test/ annuaire? Pour répondre à cette question, nous pouvons utiliser l'option "imprimer les fichiers non correspondants" de grep (-L option):

sh$ grep -iL nashorn npm/test/*
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

Remarquez comment avec le -L option la sortie de grep a changé pour n'afficher que les noms de fichiers. Ainsi, aucun des fichiers ci-dessus ne contient la chaîne "nashorn" (quel que soit le cas). Cela ne signifie pas qu'ils ne sont pas liés d'une manière ou d'une autre à cette technologie, mais au moins, les lettres "n-a-s-h-o-r-n" ne sont pas présentes.

4. Trouver des modèles dans des fichiers cachés et récursivement dans des sous-répertoires

Les deux dernières commandes utilisaient un modèle shell glob pour transmettre la liste des fichiers à examiner au grep commande.

Cependant, cela a certaines limitations inhérentes :l'étoile (* ) ne correspondra pas aux fichiers cachés. Il ne correspondra pas non plus aux fichiers (éventuellement) contenus dans les sous-répertoires.

Une solution serait de combiner grep avec la commande find au lieu de s'appuyer sur un modèle glob shell :

# This is not efficient as it will spawn a new grep process for each file
[email protected]:~$ find npm/test/ -type f -exec grep -iL nashorn \{} \;
# This may have issues with filenames containing space-like characters
[email protected]:~$ grep -iL nashorn $(find npm/test/ -type f)

Comme je l'ai mentionné comme commentaire dans le bloc de code ci-dessus, chacune de ces solutions présente des inconvénients.

Concernant les noms de fichiers contenant des caractères de type espace, je vous laisse enquêter sur le grep -z option qui, combinée avec le -print0 option de find commande, peut atténuer ce problème. N'hésitez pas à utiliser la section des commentaires à la fin de cet article pour partager vos idées sur ce sujet !

Néanmoins, une meilleure solution serait d'utiliser le "récursif" (-r ) option de grep . Avec cette option, vous donnez sur la ligne de commande la racine de votre arbre de recherche (le répertoire de départ) au lieu de la liste explicite des noms de fichiers à examiner.

Avec le -r , grep recherchera tous les fichiers dans le répertoire spécifié, y compris ceux cachés, puis il descendra récursivement dans n'importe quel sous-répertoire :

[email protected]:~$ grep -irL nashorn npm/test/npm/
npm/test/builder.js
npm/test/jasmine-browser-min.js
npm/test/jasmine-browser.js
npm/test/jasmine-node.js
npm/test/jasmine-webpack.js
npm/test/unsupported-features.js

En fait, avec cette option, je pourrais également commencer mon exploration un niveau au-dessus pour voir qu'il existe des tests non-npm qui ciblent également Nashorn :

[email protected]:~$ grep -irL nashorn npm/

Je vous laisse tester cette commande par vous-même pour voir son résultat; mais comme indice, je peux dire que vous devriez trouver beaucoup plus de fichiers correspondants !

5. Filtrer les fichiers par leur nom (en utilisant des expressions régulières)

Donc, il semble y avoir des tests spécifiques à Nashorn dans ce projet. Puisque Nashorn est Java, une autre question qui pourrait être posée serait "y a-t-il des fichiers source Java dans le projet mentionnant explicitement Nashorn ?" .

Selon la version de grep vous utilisez, il existe au moins deux solutions pour répondre à cette question.

La première consiste à utiliser grep pour trouver tous les fichiers contenant le modèle "nashorn", puis dirigez la sortie de cette première commande vers un second grep instance filtrant les fichiers sources non Java :

[email protected]:~$ grep -ir nashorn ./ | grep "^[^:]*\.java"
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

La première moitié de la commande devrait être compréhensible maintenant. Mais qu'en est-il de cette partie "^[\^:]*\\.java" ?

Sauf si vous spécifiez le -F option, grep suppose que le modèle de recherche est une expression régulière. Cela signifie qu'en plus des caractères simples qui correspondent textuellement, vous avez accès à un ensemble de métacaractères pour décrire des modèles plus complexes. Le modèle que j'ai utilisé ci-dessus ne correspondra qu'à :

  • ^ le début de la ligne
  • [^:]* suivi d'une séquence de n'importe quel caractère sauf deux-points
  • \. suivi d'un point (le point a une signification spéciale dans regex , j'ai donc dû le protéger avec une barre oblique inverse pour exprimer que je veux une correspondance littérale)
  • java et suivi des quatre lettres "java".

En pratique, depuis grep utilisera deux-points pour séparer le nom du fichier du contexte, je ne garde que les lignes ayant .java dans la section nom de fichier. Cela vaut la peine de le mentionner serait correspond aussi à .javascript noms de fichiers. C'est quelque chose que je laisse essayer de résoudre par vous-même si vous le souhaitez.

6. Filtrer les fichiers par leur nom à l'aide de grep

Les expressions régulières sont extrêmement puissantes. Cependant, dans ce cas particulier, cela semble exagéré. Sans parler de la solution ci-dessus, nous passons du temps à examiner tous les fichiers à la recherche du modèle "nashorn" - la plupart des résultats étant rejetés par la deuxième étape du pipeline.

Si vous utilisez la version GNU de grep , quelque chose qui est probable si vous utilisez Linux, vous avez une autre solution avec le --include option. Ceci indique grep pour rechercher uniquement les fichiers dont le nom correspond au modèle glob donné :

[email protected]:~$ grep -ir nashorn ./ --include='*.java'
./spec/nashorn/AsciidoctorConvertWithNashorn.java:public class AsciidoctorConvertWithNashorn {
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/AsciidoctorConvertWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/asciidoctor-convert.js"));
./spec/nashorn/BasicJavascriptWithNashorn.java:public class BasicJavascriptWithNashorn {
./spec/nashorn/BasicJavascriptWithNashorn.java:    ScriptEngine engine = engineManager.getEngineByName("nashorn");
./spec/nashorn/BasicJavascriptWithNashorn.java:    engine.eval(new FileReader("./spec/nashorn/basic.js"));

7. Trouver des mots

La chose intéressante à propos du projet Asciidoctor.js est qu'il s'agit d'un projet multilingue. À la base, Asciidoctor est écrit en Ruby, donc, pour être utilisable dans le monde JavaScript, il doit être "transpilé" à l'aide d'Opal, un compilateur source à source Ruby vers JavaScript. Une autre technologie que je ne connaissais pas auparavant.

Ainsi, après avoir examiné les spécificités de Nashorn, je me suis assigné la tâche de mieux comprendre l'API Opal. Comme première étape de cette quête, j'ai recherché toutes les mentions de l'Opal objet global dans les fichiers JavaScript du projet. Il peut apparaître dans les affectations (Opal = ), accès membre (Opal. ) ou peut-être même dans d'autres contextes. Une expression régulière ferait l'affaire. Cependant, encore une fois, grep a une solution plus légère pour résoudre ce cas d'utilisation courant. Utilisation du -w option, il ne correspondra qu'à mots , c'est-à-dire des motifs précédés et suivis d'un caractère autre qu'un mot. Un caractère non verbal est soit le début de la ligne, soit la fin de la ligne, soit tout caractère qui n'est ni une lettre, ni un chiffre, ni un trait de soulignement :

[email protected]:~$ grep -irw --include='*.js' Opal .
...

8. colorier la sortie

Je n'ai pas copié la sortie de la commande précédente car il y a beaucoup de correspondances. Lorsque la sortie est dense comme ça, vous pouvez ajouter un peu de couleur pour faciliter la compréhension. Si ce n'est pas déjà configuré par défaut sur votre système, vous pouvez activer cette fonctionnalité en utilisant le GNU --color choix :

[email protected]:~$ grep -irw --color=auto --include='*.js' Opal .
...

Vous devriez obtenir le même résultat long qu'auparavant, mais cette fois la chaîne de recherche devrait apparaître en couleur si ce n'était pas déjà le cas.

9. Compter les lignes ou les fichiers correspondants

J'ai mentionné deux fois que la sortie des commandes précédentes était très longue. Combien de temps exactement ?

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86

Cela signifie que nous avons un total 86 lignes correspondantes dans tous les dossiers examinés. Cependant, combien de fichiers différents correspondent ? Avec le -l option, vous pouvez limiter le grep afficher les fichiers correspondants au lieu d'afficher les lignes correspondantes . Ainsi, ce simple changement indiquera combien de fichiers correspondent :

[email protected]:~$ grep -irwl --include='*.js' Opal . | wc -l
20

Si cela vous rappelle le -L option, pas de surprise :comme c'est relativement courant, les minuscules/majuscules sont utilisées pour distinguer les options complémentaires. -l affiche les noms de fichiers correspondants. -L affiche les noms de fichiers qui ne correspondent pas. Pour un autre exemple, je vous laisse consulter le manuel pour le -h /-H options.

Fermons cette parenthèse et revenons à nos résultats :86 lignes correspondantes. 20 fichiers correspondants. Cependant, comment sont réparties les lignes correspondantes dans les fichiers correspondants ? Nous pouvons savoir qu'en utilisant le -c option de grep qui comptera le nombre de lignes correspondantes par fichier examiné (y compris les fichiers avec zéro correspondance) :

[email protected]:~$ grep -irwc --include='*.js' Opal .
...

Souvent, cette sortie nécessite un post-traitement car elle affiche ses résultats dans l'ordre dans lequel les fichiers ont été examinés, et elle inclut également des fichiers sans aucune correspondance, ce qui ne nous intéresse généralement pas. Ce dernier est assez facile à résoudre :

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$'

En ce qui concerne l'ordre des choses, vous pouvez ajouter la commande de tri à la fin du pipeline :

[email protected]:~$ grep -irwc --include='*.js' Opal . | grep -v ':0$' | sort -t: -k2n

Je vous laisse vérifier le sort manuel de commande pour la signification exacte des options que j'ai utilisées. N'oubliez pas de partager vos découvertes en utilisant la section des commentaires ci-dessous !

10. Trouver la différence entre deux ensembles correspondants

Si vous vous souvenez, il y a quelques commandes, j'ai cherché le mot "Opale." Cependant, si je recherche dans le même ensemble de fichiers toutes les occurrences de la chaîne "Opale", j'obtiens une vingtaine de réponses supplémentaires :

[email protected]:~$ grep -irw --include='*.js' Opal . | wc -l
86
[email protected]:~$ grep -ir --include='*.js' Opal . | wc -l
105

Trouver la différence entre ces deux ensembles serait intéressant. Alors, quelles sont les lignes contenant les quatre lettres "opale" d'affilée, mais où ces quatre lettres ne forment pas un mot entier ?

Ce n'est pas si facile de répondre à cette question. Parce que le même la ligne peut contenir les deux le mot Opal ainsi qu'un mot plus grand contenant ces quatre lettres. Mais en première approximation, vous pouvez utiliser ce pipeline :

[email protected]:~$ grep -ir --include='*.js' Opal . | grep -ivw Opal
./npm/examples.js:  const opalBuilder = OpalBuilder.create();
./npm/examples.js:  opalBuilder.appendPaths('build/asciidoctor/lib');
./npm/examples.js:  opalBuilder.appendPaths('lib');
...

Apparemment, mon prochain arrêt serait d'enquêter sur le opalBuilder objet, mais ce sera pour un autre jour.

Le dernier mot

Bien sûr, vous ne comprendrez pas l'organisation d'un projet, encore moins l'architecture du code, en émettant simplement quelques grep commandes !

Cependant, je trouve cette commande incontournable pour identifier les repères et les points de départ lors de l'exploration d'une nouvelle base de code.

J'espère donc que cet article vous a aidé à comprendre la puissance du grep commande et que vous l'ajouterez à votre coffre à outils. Nul doute que vous ne le regretterez pas !


Linux
  1. 8 exemples pratiques de la commande Linux Xargs pour les débutants

  2. 10 exemples pratiques d'utilisation de la commande scp

  3. Commande cp sous Linux :7 exemples pratiques

  4. Commande d'arrêt de Linux :5 exemples pratiques

  5. Commande nslookup :7 exemples pratiques

12 exemples pratiques d'In Command sous Linux

Les 40 exemples de commandes Go pour les développeurs Golang en herbe

15 exemples pratiques de commande Rsync sous Linux

5 exemples pratiques de la commande Tail sous Linux

15 exemples pratiques de commande Grep sous Linux / UNIX

UNIX / Linux :7 exemples pratiques de commandes PS pour la surveillance des processus