TITRE

Dans combien de circonstances sommes-nous amenés à rechercher un mot ou plus généralement une séquence de caractères dans un texte ? Et quelle diversité recouvrent ces recherches ? Il existe une commande historique sur les systèmes Unix qui offre cette fonction capitale et récurrente : grep (Global Regular Expression Print*)

Battons en brèche des idées par trop longtemps préconçues : les commandes Unix ne sont pas réservées à une caste d'administrateurs système. Elles sont aussi à votre service.

(Avertissement : vous êtes en zone Unix, la distinction entre majuscules et minuscules en est une règle quasi absolue.)

	Combien d'invités vont finalement venir ?
	Facile, il me suffit de consulter mon fichier participation.lst, constitué à cet effet, et de comptabiliser le nombre de 'oui'.
Anne-Marie	oui				\
Erwan		non				 \
Carole		OUI				  \
Marie-Jo		oui				   >		capture écran dans TextEdit
Albert		Non				  /
Damien		oui				 /

	4 oui, par conséquent 4 convives. C'est bien mais faire à l'œil la distinction entre les oui et les non, je risque fort d'en louper pour peu que la liste soit plus importante.
	Ne pourrais-je pas isoler les réponses positives ?
	Passons dans Terminal pour cela :

	grep oui participation.lst
Anne-Marie	oui
Marie-Jo		oui
Damien		oui

	3 personnes. Pas mal. C'est presque la bonne réponse. J'ai demandé à grep de trouver tous les 'oui' et pas les 'Oui', 'OUI' ou 'oUi', Il fait bien son travail mais ça ne m'arrange pas dans ce cas. Une idée pour contourner cette rigueur toute binaire ?

	grep -i oui participation.lst			( -i pour ignore case ou ignorer la casse)
Anne-Marie	oui
Carole		OUI
Marie-Jo		oui
Damien		oui

	On retrouve 4. C'est nettement mieux. Ceci dit, il me reste à compter la main. Fantasmez un instant que l'on ait là les participants à une conférence de Steve Jobs et qu'il nous faille trouver la salle en conséquence ;-)
L'on m'avait laissé entendre que l'informatique c'était génial car ça pouvait faire tout le travail à notre place. Pourrais-je avoir juste le compte ?

	grep -i -c oui participation.lst		( -c pour count ou compter)
										(note : on peut dans le cas présent regrouper les options en -ci ou -ic)
	4	Clair, sobre, en un mot lumineux !
	Ma liste s'enrichit, la ligne suivante y est ajoutée :
Louis		non

	Que se passe-t-il alors quand je relance mon dénombrement ?

	grep -i -c oui participation.lst

	5	GROS SOUCI ! Heureusement que je ne calcule pas encore mes impôts à l'aide de grep. Louis ne sera pas présent et pourtant le nombre de participants augmente. Logique ! Dans Louis il y a 'L', 'oui' et 's'. En effet nous n'avons jamais défini en quel(s) endroit(s) de la ligne nous cherchions la séquence de caractère 'o', 'u' et 'i'. Pour pallier??remédier à cet inconvénient majeur et loin d'être trivial, nous avons à notre disposition une multitude solutions. Essayons :

	grep -i -w -c oui participation.lst

	4	Correct ! Quelle est la magie introduite par l'option -w. Elle signifie word (mot) et signifie que la suite de caractère doit représenter un mot complet et non un sous-ensemble??morceau??partie de mot. Nous tablons ici sur le fait qu'aucun prénom ou patronyme d'invité ne se résumera au mot 'oui'. Parmi toutes les alternatives possibles :

	grep -ic 'oui$' participation.lst

	4	Toujours correct, Ouf ! Cette commande nous permet de découvrir une autre facette importante de grep, les expressions régulières, un simple caractère spécial dans le cas présent. Le dollar, placé en fin de chaîne à rechercher, symbolise une fin de ligne. Autrement dit, nous partons cette fois de l'hypothèse que les indications de participation seront toujours placées très exactement à l'extrémité de chaque ligne. Tout aussi important le couple d'apostrophes qui délimite cette chaîne. En effet le dollar a aussi une signification toute particulière aux yeux de l'interpréteur de commandes (le shell) à qui nous soumettons l'expression entière (nom de la commande, options, paramètres, etc). En entourant ainsi le $, nous le protégeons en empêchant son interprétation par le shell pour la réserver à grep.

	Mais la vie n'est jamais aussi simple. Elle n'est qu'adversité et contrariété. Qu'advient-il si un quidam est intervenu sur cette liste en utilisant une autre convention que celle consistant à employer exclusivement oui et non ? Imaginez notre désarroi quant à la découverte de lignes telles que :

Bertrand		OK
Claude		Yes

Sommes-nous obligés d'intervenir sur le fichier pour remplacer tous les ok et yes par des oui, au risque de retrouver le problème à chaque mise à jour de ce fichier ? Une fois de plus, grep sait contourner la difficulté :

	grep -Eiwc 'ok|oui|yes' participation.lst

	6	Et oui, 2 convives de dernière minute, c'est bien cela. Deux nouveaux éléments : la barre se séparation verticale qui est interprétée par grep comme un choix entre les deux possibilités présentes de part et d'autre de ce symbole… À condition, et c'est le deuxième point, que l'on emploie l'option -E ( -E pour extended ou étendu). Le mode étendu autorise en fait l'emploi d'une syntaxe, composée de symboles spéciaux et même de mots-clefs, plus riche mais aussi potentiellement plus compliquée. En réalité cette dernière commande aurait pu s'écrire de deux autres façons qui divergent à peine :
	egrep -iwc 'ok|oui|yes' participation.lst
	grep -iwc 'ok\|oui\|yes' participation.lst

La première variante use de la déclinaison egrep de la commande grep. L'option -E permet de profiter des possibilités d'egrep avec grep (les gurus Unix recommandent grep -E plutôt qu'egrep).
La deuxième variante fait appel au caractère \ (backslash ou antislash) pour notifier à grep la signification particulière que l'on veut donner alors à notre barre verticale. 

L'événement une fois terminé??clos, il serait utile de connaître le nombre de non-participants, ne serait-ce que pour mieux cibler nos invitations lors d'une prochaine manifestation. Faut-il repenser notre commande ou même tout recompter ?

	grep -Eiwcv 'ok|oui|yes' participation.lst

	3	Erwan, Albert et Louis. Le compte est bon. Remarquez-vous ? Une seule option en plus permet d'inverser le résultat : -v (inVert match ou inVerser le résultat) sélectionne les lignes qui NE correspondent PAS avec l'expression à trouver. Notre expression étant au fil du temps devenue relativement complexe, le plus efficace a été de trouver l'opposé plutôt que de fabriquer  une nouvelle recherche.
ATTENTION : cette solution n'est toutefois pas sans risque, la moindre ligne vide par exemple dans notre fichier participation.lst sera comptabilisée comme une personne n'étant pas venue. ?? comme une absence.

Abandonnons nos invités et intéressons nous à d'autres domaines d'application.

grep est régulièrement utilisée pour filtrer les lignes qui nous intéressent d'un flot d'informations (ce que l'on désigne aussi sous le nom d'entrée standard - standard input -, par opposition à un fichier statiquement stocké sur un média). La plupart du temps, cela prend la forme d'une commande dont on manipule le résultat qui sans cela s'afficherait dans votre fenêtre Terminal.
Concrètement, si vous exécutez la commande AppleSystemProfiler, vous allez être submergé par une grosse quantité de données (un de ces fameux flux d'informations) alors que peut être une toute petite portion nous intéresse.
Une des prérogatives de grep est de permettre justement de se focaliser sur les éléments essentiels à un instant précis. Réessayer cette fois l'enchaînement de commandes suivant :
	AppleSystemProfiler | grep -A 10 "Disque dur:"

    Disque dur:
        +----------------------------------------------------------------------+
        |                                                                      |
        |  Taille du disque              :  9.55 GB (1K = 1024)  11 GB (1K = 1000) |
        |  Numéro de l’unité             :  0                                  |
        |  Type de périphérique ATA      :  ata                                |
        |  Nº série du périphérique      :  WD-WM6570816085                    |
        |  Révision du périphérique      :  83.10A83                           |
        |  Modèle du périphérique        :  WDC WD102AA                              |
        |                                                                      |
        +----------------------------------------------------------------------+
	N'est ce pas plus lisible ? Ici, le résultat produit par AppleSystemProfiler est redirigé à l'aide d'un tube de communication symbolisé par la barre verticale qui relie les deux commandes (c'est un caractère spécial de l'interpréteur de commandes, le shell, dénommé "pipe" - tuyau en français ou l'abréviation de pipeline -).
Plutôt que d'extraire les données recherchées depuis un fichier, grep traite les lignes en provenance directe de la commande directement à gauche du "pipe". De ces lignes, il dégage celles contenant la chaîne "Disque dur:" (le couple d'apostrophes est important car il permet de conserver à l'espace son caractère littéral, dans le cas contraire, il est interprété comme séparateur d'arguments par le shell et dur: serait alors pris pour un nom de fichier dans lequel rechercher le mot Disque). L'option -A (A pour After ou Après) nous permet de compléter les lignes trouvées par les 10 (l'argument qui suit immédiatement -A) qui suivent juste après. Dans la même veine, il existe également les options -B (B pour Before ou avant ou encore précédant) et -C (C pour Context), une sorte de combinaison de -A et -B.

Revenons maintenant un instant sur cette notion d'expression régulière. Qui penserait de prime abord que grep pourrait faire le bonheur des cruciverbistes et autres verbicrucistes ? Voyons cela par la pratique, je cherche un mot de 7 lettres dont je connais les deuxième, troisième, cinquième et dernière lettre, respectivement 'o', 'r', 'u' et 'e'. Une idée pour ne pas sécher sur votre grille ? Allez, je vous affranchis (-:
	grep '^.or.u.e$' /usr/share/dict/web2
bordure
cornule
cornute
foreuse
formule
fortune
morsure
torture

	Décortiquons. Nous avons déjà vu le symbole $, l'accent circonflexe est son contraire et symbolise donc un début de ligne. Le point se substitue à un caractère et un seul, n'importe lequel. En cherchant dans le fichier web2, nous trouvons donc une liste de mots (ce fichier en stocke un et un seul par ligne, ce qui simplifie grandement notre travail) qui correspondent parfaitement à notre expression.
Comment cela, ce n'est pas le but du jeu ? Comment cela je triche ?   Bande de jaloux !
C'est pas mal mais ne pouvons-nous pas élargir notre recherche à un fichier de noms propres ? Si fait (note : avec une autre combinaison de lettres à trouver dans l'exemple qui suit) :
	grep -i -h '^ar.en.$' /usr/share/dict/web2 /usr/share/dict/propernames
ardent
argent
Arleng
arpent
arrent
arseno
Arlene

	Vous pouvez fournir à grep autant de fichiers à traiter que vous le souhaitez. -i est nécessaire cette fois car le fichier propernames contient des lettres majuscules, les initiales des noms propres. -h évite l'affichage du nom de fichier qui préfixe chaque ligne trouvée, il ne nous est d'aucune utilité.

Nouvel usage.
De nombreux fichiers de configuration Unix sont largement documentés au point que la part donnée aux explications est plusieurs fois supérieure aux valeurs contenues dans les fichiers en question. Essayez donc de visualiser le fichier /etc/cups/cupsd.conf (le moyen le plus simple est sûrement  cat /etc/cups/cupsd.conf). Indigeste, n'est-il pas ?
Que faire pour n'en montrer que les lignes véritablement "actives" ?
	grep -Env '^[:blank:]*(#|$)' /etc/cups/cupsd.conf
52:ServerName 127.0.0.1
159:LogLevel info
	:
	:	
764:Allow From 127.0.0.1
767:</Location>

	Résultat : seulement une vingtaine de lignes sur les quelques 770 que contient le fichier cupsd.conf. Concluant ?
Un condensé de notions expliquées en amont mâtiné de menus ajouts comme [:blank:] qui représente une tabulation ou un espace. L'astérisque qui suit immédiatement est très important et signifie "n'importe quelle quantité, y compris nulle, du symbole qui précède", autrement dit ici, n'importe quelle combinaison ininterrompue d'espaces et de tabulations. Enfin, l'expression est terminée par soit un caractère dièse soit une fin de ligne symbolisée par le dollar vu précédemment. Le dièse est pris pour ce qu'il représente et rien de plus simplement comme il sert souvent à introduire un commentaire dans les fichiers de configuration Unix, nous indiquons ainsi que nous recherchons les lignes vides, celles remplies de "blancs" et celles ne comportant que des commentaires. Comme nous utilisons l'option -v, nous obtenons un résultat opposé à l'objet de notre recherche.
L'option -n, totalement facultative, préfixe chaque occurrence trouvée par son numéro de ligne dans le fichier. Cela pourra se révéler très pratique lorsque l'on utilisera d'autres programme comme vi notamment ou ne serait-ce que pour y faire référence dans une communication avec un tiers "regarde, ton problème se situe à la ligne ..." 

Un autre cas fréquent quand on administre un système de type Unix est de localiser le fichier de configuration approprié. Dans la jungle des fichiers qui peuplent le dossier principal /etc et ses recoins (ses sous-dossiers), comment mettre la main sur celui ou ceux qui contiennent le mot DocumentRoot (que les aficionados du célèbre logiciel Apache auront instantanément reconnu) ?
	grep -srl DocumentRoot /etc
/etc/httpd/httpd.conf
/etc/httpd/httpd.conf.default
/etc/httpd/httpd.conf.applesaved

	L'option importante ici est -r pour récursif (recursive en anglais). Elle ordonne à grep de poursuivre son travail dans les sous-dossiers et pas de se cantonner à un seul niveau de hiérarchie comme c'est le cas par défaut.
	-l pour liste (sous entendu des noms de fichiers) permet de se focaliser exclusivement sur les noms des fichiers qui satisfont à la recherche sans afficher le détail des lignes qui en leur sein contiennent l'expression recherchée.
	-s comme silencieux supprime les éventuels messages d'erreurs et autres avertissements comme le fait d'essayer de lire un fichier sur lequel vous n'avez pas les droits ou de lire un dossier comme s'il s'agissait d'un fichier.

Pas encore convaincu de l'extraordinaire utilité de grep ?
À votre avis, que peut bien faire la commande suivante ? 
	grep -Ew "(.*) \1" courrier.txt

Suite à notre notre discussion de l'instant...
	Le résultat vous met-il sur une voie ? Ne remarquez-vous pas le double "notre". Voilà ce que notre ami grep nous aide présentement à détecter. L'expression .* (point astérisque) correspond à n'importe quelle séquence de caractères (uniquement des mots à cause de l'option -w) et \1 est mis en correspondance avec le mot délimité par le premier niveau de parenthèses (\2 pour le deuxième niveau de parenthèses, et ainsi de suite). En clair, si l'on trouve la suite UN_MOT espace UN_MOT (le même que le premier), l'expression est vérifiée.

Encore un autre emploi ? Allez, un petit coup d'esbroufe pour clore le sujet (inspiré par le livre "Unix Power Tools" chez O'Reilly) :

open -e `grep -l "EXPRESSION" *.txt`

[CAPTURE ECRAN ICI]

grep est bien une commande "tout-terrain".

--

Récapitulatif
	Fonction
		Recherche une séquence de caractères dans des données textuelles
	Options vues
		-i	
		-c	
		-v	
		-E	
		-w	
		-A		(et incidemment -B et -C)
		-h	
		-n
		-l
		-r		
		-s	
		Note : ces options ne représentent qu'une faible portion de celles offertes par grep.
	Expressions et caractères ou spéciaux
		^
		$
		|
		.
		*
		()
		\
		[:blank:]
	Points importants
		- NE MODIFIE PAS SA SOURCE
		- facilite/permet l'élaboration d'automates (script)
		- pratique pour traiter les fichiers masqués par le Finder

Déclinaisons
	formes dérivées plus ou moins spécialisées
		Exemples : egrep, fgrep, rcsgrep, hrefgrep, srcgrep, taggrep, webfgrep (package webgrep de même que les 3 précédentes), sgrep, hgrep, agrep, zipgrep, pcregrep
	habillage d'une couche graphique
		NisusWriter's PowerFind, SpeedSearch X, grepArtee
	interface ou intégration dans langages de programmation
		Exemple : Perl

Limitations
	Il est bien dommage de cantonner grep à l'étude de fichiers texte (txt, html, sources de programmes de tous langages, fichiers "systèmes"). En effet cette commande ne vous sera que d'une bien maigre assistance dans l'exploration de fichiers "codés" comme la plupart des formats propriétaires des suites bureautiques et encore moins sur des fichiers PDF dont les données textuelles entres autres sont quasi systématiquement compressées.

Documentation
	pages HTML sur http://www.gnu.org/software/grep/doc/grep.html
			  et  http://www.eleves.ens.fr/tuteurs/unix/exercices/grep.html
	man grep

Encadré

* Les avis semblent partagés sur la signification exacte des lettres de l'acronyme. Le "Global" cède parfois la place à "General" et "Print" à "Parser" pour devenir par exemple General Regular Expression Parser.