GNU/Linux >> Tutoriels Linux >  >> Linux

Manipuler du texte en ligne de commande avec grep

Imaginez que vous avez un fichier (ou un groupe de fichiers) et que vous souhaitez rechercher une chaîne ou un paramètre de configuration spécifique dans ces fichiers. Ouvrir chaque fichier individuellement et essayer de trouver la chaîne spécifique serait fastidieux et n'est probablement pas la bonne approche. Alors, que pouvons-nous utiliser ?

Il existe de nombreux outils que nous pouvons utiliser dans les systèmes basés sur *nix pour rechercher et manipuler du texte. Dans cet article, nous aborderons le grep commande pour rechercher des modèles, qu'ils soient trouvés dans des fichiers ou provenant d'un flux (un fichier ou une entrée provenant d'un tube, ou | ). Dans un prochain article, nous verrons également comment utiliser sed (Stream Editor) pour manipuler un flux.

La meilleure façon de comprendre le fonctionnement d'un programme ou d'un utilitaire est de consulter sa page de manuel. De nombreux outils Unix (sinon tous) fournissent des pages de manuel lors de l'installation. Sur les systèmes basés sur Red Hat Enterprise Linux, nous pouvons exécuter ce qui suit pour répertorier grep Fichiers de documentation :

$ rpm -qd grep
/usr/share/doc/grep/AUTHORS
/usr/share/doc/grep/NEWS
/usr/share/doc/grep/README
/usr/share/doc/grep/THANKS
/usr/share/doc/grep/TODO
/usr/share/info/grep.info.gz
/usr/share/man/man1/egrep.1.gz
/usr/share/man/man1/fgrep.1.gz

Avec les pages de manuel à notre disposition, nous pouvons maintenant utiliser grep et explorez ses options.

grep bases

Dans cette partie de l'article, nous utilisons les words fichier, que vous pouvez trouver à l'emplacement suivant :

$ ls -l /usr/share/dict/words 
lrwxrwxrwx. 1 root root 11 Feb  3  2019 /usr/share/dict/words -> linux.words

Ce fichier contient 479 826 mots et est fourni par les words emballer. Dans mon système Fedora, ce paquet est words-3.0-33.fc30.noarch . Lorsque nous listons le contenu des words fichier, nous voyons la sortie suivante :

$ cat /usr/share/dict/words
1080
10-point
10th
11-point
[……]
[……] 
zyzzyva
zyzzyvas
ZZ
Zz
zZt
ZZZ

Ok, donc nous avons dit les words le fichier contenait 479 826 lignes, mais comment le savons-nous ? Rappelez-vous, nous avons parlé des pages de manuel plus tôt. Voyons si grep offre une option pour compter les lignes dans un fichier donné.

Ironiquement, nous utiliserons grep grep pour l'option comme suit :

Donc, nous avons évidemment besoin de -c , ou l'option longue --count , pour compter le nombre de lignes dans un fichier donné. Compter les lignes dans /usr/share/dict/words donne :

$ grep -c '.' /usr/share/dict/words 
479826

Le '.' signifie que l'on comptera toutes les lignes contenant au moins un caractère, espace, blanc, tabulation, etc.

Basic grep expressions régulières

Le grep La commande devient plus puissante lorsque nous utilisons des expressions régulières (regexes). Donc, pendant que nous nous concentrons sur le grep commande elle-même, nous aborderons également la syntaxe de base des expressions régulières.

Supposons que seuls les mots commençant par Z nous intéressent . C'est dans cette situation que les expressions régulières sont utiles. Nous utilisons le carat (^ ) pour rechercher des motifs commençant par un caractère spécifique, indiquant le début d'une chaîne :

Pour rechercher des modèles se terminant par un caractère spécifique, nous utilisons le signe dollar ($ ) pour indiquer la fin de la chaîne. Voir l'exemple ci-dessous où nous recherchons des chaînes se terminant par hat :

Pour imprimer toutes les lignes contenant hat quelle que soit sa position, que ce soit au début ou à la fin de la ligne, nous utiliserions quelque chose comme :

Le ^ et $ sont appelés métacaractères et doivent être précédés d'une barre oblique inverse (\ ) lorsque nous voulons faire correspondre ces caractères littéralement. Si vous souhaitez en savoir plus sur les métacaractères, consultez https://www.regular-expressions.info/characters.html.

Exemple :Supprimer des commentaires

Maintenant que nous avons gratté la surface de grep , travaillons sur des scénarios réels. De nombreux fichiers de configuration dans *nix contiennent des commentaires décrivant différents paramètres dans le fichier de configuration. Le /etc/fstab , fichier par exemple, a :

$ cat /etc/fstab 

#
# /etc/fstab
# Created by anaconda on Thu Oct 27 05:06:06 2016
#
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VGCRYPTO-ROOT /                       ext4    defaults,x-systemd.device-timeout=0 1 1
UUID=e9de0f73-ddddd-4d45-a9ba-1ffffa /boot                   ext4    defaults        1 2
LABEL=SSD_SWAP		swap		swap		defaults	0 0
#/dev/mapper/VGCRYPTO-SWAP swap                    swap    defaults,x-systemd.device-timeout=0 0 0

Les commentaires sont marqués par le hash (# ), et nous voulons les ignorer lors de l'impression. Une option est le cat commande :

$ cat /etc/fstab | grep -v '^#' 

Cependant, vous n'avez pas besoin de cat ici (évitez l'utilisation inutile du chat). Le grep est parfaitement capable de lire des fichiers, donc à la place, vous pouvez utiliser quelque chose comme ceci pour ignorer les lignes qui contiennent des commentaires :

$ grep -v '^#' /etc/fstab 

Si vous souhaitez envoyer la sortie (sans commentaires) vers un autre fichier à la place, vous utiliserez :

$ grep -v '^#' /etc/fstab > ~/fstab_without_comment

Tandis que grep peut formater la sortie à l'écran, cette commande est incapable de modifier un fichier en place. Pour ce faire, nous aurions besoin d'un éditeur de fichiers comme ed . Dans le prochain article, nous utiliserons sed pour obtenir la même chose que nous avons fait ici avec grep .

Exemple :Supprimer les commentaires et les lignes vides

Pendant que nous sommes encore sur grep , examinons le /etc/sudoers dossier. Ce fichier contient de nombreux commentaires, mais nous ne nous intéressons qu'aux lignes qui n'ont pas de commentaires, et nous voulons également nous débarrasser des lignes vides.

Donc, d'abord, supprimons les lignes contenant les commentaires. La sortie suivante est produite :

# grep -v '^#' /etc/sudoers 

Defaults   !visiblepw

Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root	ALL=(ALL) 	ALL
%wheel	ALL=(ALL)	ALL

Maintenant, nous voulons nous débarrasser des lignes vides (vides). Eh bien, c'est facile, lancez simplement un autre grep commande :

# grep -v '^#' /etc/sudoers | grep -v '^$' 
Defaults   !visiblepw
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root	ALL=(ALL) 	ALL
%wheel	ALL=(ALL)	ALL
valentin.local	ALL=NOPASSWD: /usr/bin/updatedb

Peut-on faire mieux ? Pourrions-nous exécuter notre grep commande pour être plus conviviale pour les ressources et ne pas bifurquer grep à deux reprises? Nous pouvons certainement :

# grep -Ev '^#|^$' /etc/sudoers 
Defaults   !visiblepw
Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"
Defaults    secure_path = /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
root	ALL=(ALL) 	ALL
%wheel	ALL=(ALL)	ALL
valentin.local	ALL=NOPASSWD: /usr/bin/updatedb

Ici, nous avons introduit un autre grep option, -E (ou --extended-regexp ) <PATTERN> est une expression régulière étendue.

Exemple :Imprimer uniquement /etc/passwd utilisateurs

Il est évident que grep est puissant lorsqu'il est utilisé avec des regex. Cet article ne couvre qu'une petite partie de ce que grep est vraiment capable de. Pour démontrer les capacités de grep et l'utilisation d'expressions régulières, nous analyserons le /etc/passwd classer et imprimer uniquement les noms d'utilisateur.

Le format du /etc/passwd fichier est le suivant :

$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin

Les champs ci-dessus ont la signification suivante :

<name>:<password>:<UID>:<GID>:<GECOS>:<directory>:<shell>

Voir man 5 passwd pour plus d'informations sur le /etc/passwd dossier. Pour imprimer uniquement les noms d'utilisateur, nous pourrions utiliser quelque chose comme ceci :

$ grep -Eo '^[a-zA-Z_-]+' /etc/passwd
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
operator

Dans le grep ci-dessus commande, nous avons introduit une autre option :-o (ou --only-matching ) pour afficher uniquement la partie d'une ligne correspondant à <PATTERN> . Ensuite, nous avons combiné -Eo pour obtenir le résultat souhaité.

Nous allons maintenant décomposer la commande ci-dessus afin de mieux comprendre ce qui se passe réellement. De gauche à droite :

  • ^ correspond au début de la ligne.
  • [a-zA-Z_-] est appelée une classe de caractères et correspond à un seul caractère correspondant à la liste incluse.
  • + est un quantificateur qui correspond entre une et un nombre illimité de fois.

L'expression régulière ci-dessus se répétera jusqu'à ce qu'elle atteigne un caractère auquel elle ne correspond pas. La première ligne du fichier est :

root:x:0:0:root:/root:/bin/bash

Il est traité comme suit :

  1. Le premier caractère est un r , donc il correspond à [a-z] .
  2. Le + passe au caractère suivant.
  3. Le deuxième caractère est un o et cela correspond à [a-z] .
  4. Le + passe au caractère suivant.

Cette séquence se répète jusqu'à ce que nous frappions les deux-points (: ). La classe de caractères [a-zA-Z_-] ne correspond pas au : symbole, donc grep passe à la ligne suivante.

Puisque les noms d'utilisateur dans le passwd fichier sont tous en minuscules, nous pourrions également simplifier notre classe de caractères comme suit, et toujours obtenir le résultat souhaité :

$ grep -Eo '^[a-z_-]+' /etc/passwd

Exemple :Rechercher un processus

Lors de l'utilisation de ps pour grep pour un processus, nous utilisons souvent quelque chose comme :

$ ps aux | grep ‘thunderbird’

Mais le ps la commande ne listera pas seulement le thunderbird processus. Il répertorie également le grep commande que nous venons d'exécuter également, depuis grep s'exécute également après le tube et s'affiche dans la liste des processus :

$ ps aux | grep thunderbird
val+  2196  0.7  2.1 52 33 tty2  Sl+ 16:47  1:55 /usr/lib64/thunderbird/thunderbird
val+ 14064  0.0  0.0 57 82 pts/2  S+   21:12   0:00 grep --color=auto thunderbird

Nous pouvons gérer cela en ajoutant grep -v grep pour exclure grep à partir de la sortie :

$ ps aux | grep thunderbird | grep -v grep
val+  2196  0.7  2.1 52 33 tty2  Sl+ 16:47  1:55 /usr/lib64/thunderbird/thunderbird

Lors de l'utilisation de grep -v grep fera ce que nous voulions, de meilleurs moyens existent pour obtenir le même résultat sans créer un nouveau grep processus :

$ ps aux | grep [t]hunderbird 
val+  2196  0.7  2.1 52 33 tty2  Sl+ 16:47  1:55 /usr/lib64/thunderbird/thunderbird

Le [t]hunderbird correspond ici au littéral t , et est sensible à la casse. Il ne correspondra pas à grep , et c'est pourquoi nous ne voyons plus que thunderbird dans la sortie.

Cet exemple est juste une démonstration de la flexibilité de grep est, ne vous aidera pas à dépanner votre arborescence de processus. Il existe de meilleurs outils adaptés à cette fin, comme pgrep .

Conclusion

Utilisez grep lorsque vous souhaitez rechercher un motif, soit dans un fichier, soit dans plusieurs répertoires de manière récursive. Essayez de comprendre comment fonctionnent les expressions régulières lorsque grep , car les expressions régulières peuvent être puissantes.

[Vous voulez essayer Red Hat Enterprise Linux ? Téléchargez-le maintenant gratuitement.]


Linux
  1. Soyez trié avec sort en ligne de commande

  2. Travailler avec des flux de données sur la ligne de commande Linux

  3. Travailler avec des canaux sur la ligne de commande Linux

  4. Manipulation de texte en ligne de commande avec sed

  5. Multi-tâches en ligne de commande avec screenie

Comment utiliser Nano, l'éditeur de texte en ligne de commande Linux

Utilisation de la commande GREP sous Linux avec des exemples

Maîtrisez la ligne de commande Linux

Le didacticiel de la commande Grep avec des exemples pour les débutants

Manipuler du texte avec sed et grep

Suivi du temps avec Timewarrior en ligne de commande