Journal La commande ack, one step beyond grep !

Posté par  (site web personnel) . Licence CC By‑SA.
26
29
nov.
2021

L'URL du site de la commande ack annonce la couleur1 : https://beyondgrep.com/. J'ai l'habitude d’agripper les motifs avec grep, mais je m'essaie depuis quelques temps à les acquérir avec ack 2. Le deuxième et dernier journal sur cette commande datant d'avril 2013 (voir le tag ack), il est temps de faire une piqûre de rappel aux citoyens du libre.

Version 3

En 2019, ack est passée en version 3. La version actuelle est la 3.5.0 (mars 2021), et la version disponible dans Ubuntu 21.10 est la 3.4.0. Les nouveautés sont résumées sur la page principale du site.

La commande est écrite en Perl 5 et les dépendances sont minimales :

$ apt show ack
[...]
Depends: libfile-next-perl (>= 1.18), perl:any
Breaks: ack-grep (<= 2.14-5~)
Replaces: ack-grep (<= 2.14-5~)
[...]

Cela permet de la proposer facilement pour la plupart des systèmes d'exploitation : Linux, macOS, *BSD et Windows.

On voit également que dans Ubuntu la commande s'appelait auparavant ack-grep, soit 100 % plus long que grep. Devenue ack, elle prend l'avantage en étant 25 % plus courte ;-)

Usages

Chercher dans les contenus des fichiers

Étant écrite en Perl, ack utilise bien sûr les expressions régulières Perl 3 de façon native. L'usage en est très simple :

ack [options] PATTERN [FILE...]

Un des avantages de ack sur grep est qu'elle utilise par défaut un certain nombre d'options utiles : récursion des répertoires, affichage des numéros de lignes, coloration syntaxique et surbrillance du motif recherché (sauf redirection)… De plus, elle ignore par défaut de nombreux fichiers (images, archives, sauvegardes, PDF…) et répertoires (.git, __pycache__, CMakeFiles…), ce qui participe à sa rapidité. La commande ack --dump vous en donnera la liste avec une syntaxe limpide.

Les principales fonctionnalités de ack et d'autres alternatives à grep sont résumées dans ce tableau. Voici une courte sélection personnelle parmi les nombreuses options disponibles :

-l, --files-with-matches      Print filenames with at least one match
-i, --ignore-case             Ignore case distinctions in PATTERN                             
-w, --word-regexp             Force PATTERN to match only whole words
-m, --max-count=NUM           Stop searching in each file after NUM matches
-C [NUM], --context[=NUM]     Print NUM lines (default 2) of output context.
-t X, --type=X                Include only X files, where X is a filetype,
                                e.g. python, html, markdown, etc
-s                            Suppress error messages about nonexistent or unreadable files.

Notez que l'option -t peut être utilisée encore plus simplement, par exemple :

$ ack LinuxFr --markdown

L'option peut facilement être inversée pour au contraire éviter certains fichiers : --nomarkdown.
Pour déterminer le type d'un fichier, la commande se base non seulement sur les extensions des noms de fichiers mais aussi sur les shebang. Les types disponibles peuvent être obtenus avec à nouveau la commande ack --dump.

Chercher dans les noms ou les types de fichiers

Avec l'option -g, on peut chercher le motif dans les noms des fichiers plutôt que dans leur contenu. Par exemple, cherchons des fichiers de configuration cachés :

$ ack -g ^[.].*rc$

Avec l'option -f on pourra par exemple afficher simplement la liste des fichiers d'un type donné présents dans une arborescence :

$ ack -f --shell

Personnalisation

Pour personnaliser le comportement de la commande, on peut créer un fichier de configuration contenant toutes les options et paramètres définis par défaut :

$ ack --create-ackrc > ~/.ackrc

Exemple concret, j'aime bien utiliser des terminaux avec caractères noirs sur fond jaune clair mais par défaut ack affiche les numéros de ligne en jaune. J'ai donc simplement ajouté dans mon .ackrc la ligne suivante :

--color-lineno=Red

Conclusion

ack est le genre de commande que l'on risque d'adopter rapidement après essai : simple, rapide, efficace, agréable à utiliser, comportement facilement personnalisable… Il est même possible de l'appeler depuis certains outils tels que vim ou emacs.

Mais il est vrai que grep bénéficie de la prime au premier entrant. Pour un script à distribuer, grep a l'avantage d'être installée sur tous les systèmes libres, même si ses variantes peuvent éventuellement introduire quelques problèmes de compatibilité.

En tout cas, pour votre usage quotidien vous risquez vraiment d'être séduit(e)s par ack.

Acknowledgements

ack est essentiellement l'oeuvre d'Andy Lester, alias petdance sur GitHub. Elle est sous licence Artistic License 2.0.

Références


  1. Prince Buster, One Step Beyond, 1964. 

  2. Auverlot Olivier, "Ack, le super grep", Linux Pratique, HS n°52, octobre 2021, https://connect.ed-diamond.com/linux-pratique/lphs-052/ack-le-super-grep 

  3. Bernard Desgraupes, Introduction aux expressions régulières, Paris : Vuibert, 2e édition, 2008, ISBN 978-2-7117-4867-9. 

  • # Ag / The Silver Searcher

    Posté par  (site web personnel) . Évalué à 6.

    Dans le même style, il y a aussi Ag, qui se veut plus rapide que Ack.

  • # récursivité

    Posté par  (Mastodon) . Évalué à 6.

    La version gnu de grep supporte la récursivité des répertoires (-r).

    • [^] # Re: récursivité

      Posté par  (site web personnel) . Évalué à 5.

      Oui, j'utilise la plupart du temps grep -inRI :

      • i : insensible à la casse,
      • n : numéros de ligne,
      • R : récursion (avec suivi des liens symboliques),
      • I : exclusion des binaires.

      Ce qui est à peu près équivalent à ack -i. Je pourrais d'ailleurs inclure --ignore-case dans le fichier de configuration de ack pour simplifier. Et ça pourrait alors être annulé par l'option -I.

      A noter que dans grep on peut utiliser des regex Perl en ajoutant l'option -P. Avec ack, c'est par défaut. On a également dans grep l'option --color, qui est activée par défaut dans ack.

      • [^] # Re: récursivité

        Posté par  . Évalué à 2.

        D'aucuns préfèreront :
        grep -sPqR

        • [^] # Re: récursivité

          Posté par  (site web personnel) . Évalué à 3.

            -s, --no-messages         supprimer les messages d'erreur
            -P, --perl-regexp         MOTIFS sont des expressions rationnelles Perl
            -q, --quiet, --silent     supprimer tout affichage vers la sortie standard
            -R, --dereference-recursive  similaire, mais avec suivi des liens symboliques
          
          • [^] # Re: récursivité

            Posté par  . Évalué à 2.

            J'ai l'impression que le jeu de mots n'a pas pris.
            INRI (Jésus) <> SPQR (Empire romain)

            • [^] # Re: récursivité

              Posté par  (site web personnel) . Évalué à 3. Dernière modification le 06 décembre 2021 à 13:41.

              Effectivement, celui-là je ne le connaissais pas ! L'option -q (quietus) me semblait bizarre, mais… :-) Merci

  • # Utiliser find

    Posté par  (site web personnel) . Évalué à 10.

    Dans les Unix il y a une commande find qui permet de réaliser toutes commandes propres aux fichiers que fait “ack”.

    Par exemple pour “utiliser grep sur les noms de fichiers” on fait

    % find . | grep 'pattern'

    mais on peut être plus restrictif sur les fichiers qu'on cherche avec find.

    Pour utiliser grep seulement sur les fichiers markdown par exemple:

    % find . -type f -name '*.md' -exec grep 'pattern' '%' '+'

    C'est un peu plus abscons à cause de '%' et '+' mais beaucoup plus flexible. Par exemple je faisais régulièrement des recherches de type “chercher tel nom de variable dans les fichiers shell et terraform que j'ai manipulés dans les derniers jours”

    L'avantage d'appendre find est que c'est très flexible et qu'on peut le faire marcher avec tous les programmes. C'est notamment très utile avec grep, sed (inplace), ou ed pour commencer.

    • [^] # Re: Utiliser find

      Posté par  (site web personnel) . Évalué à 9.

      Autre version:

      % find . -type f -name '*.md' -print0 | xargs -0  grep 'pattern'
    • [^] # Re: Utiliser find

      Posté par  (site web personnel) . Évalué à 3.

      C'est sûr que find ne vas pas être détrôné par ack.

      Mais un aspect intéressant de ack est qu'il ne se contente pas d'utiliser une seule extension de fichier. Par exemple, un fichier xml est détecté avec ces paramètres :

        --type-add=xml:ext:xml,dtd,xsd,xsl,xslt,ent,wsdl
        --type-add=xml:firstlinematch:/<[?]xml/
      

      Et on peut personnaliser le fichier de configuration pour ajouter d'autres définitions pour un type donné, ou de nouveaux types. Cette simplicité pour personnaliser le comportement de la commande me semble un des points forts de ack.

    • [^] # Re: Utiliser find

      Posté par  . Évalué à 4.

      Ou les globbings étendus qui sont plus pratiques encore

      find . -type f -name '*.md' -exec grep 'pattern' '%' '+'

      devient

      grep 'pattern' **/*.md(.)

      Et ça marche avec toutes les commandes aussi (tant que tu n'explose pas le nombre d'argument de ta ligne de commande).

      Les globbings sont plus pratiques que find, mais moins rapide, mais bien des fois c'est ta vitesse de frappe qui prend le plus de temps donc ça vaut le coup.

      Néanmoins j'utilise abondamment ripgrep parce qu'il a une vitesse folle (même en rapport à find avec le '+' dans le exec ou avec xargs/parallel).

      https://linuxfr.org/users/barmic/journaux/y-en-a-marre-de-ce-gros-troll

  • # Merci pour les découvertes

    Posté par  (site web personnel) . Évalué à 3.

    J'utilise ack depuis quelques années et j'adore, je l'ai choisi à l'époque car il est PCRE par défaut contrairement à grep.

    Merci pour les deux découvertes du jour, ag d'une part, que je viens de tester, c'est effectivement impressionnant en terme de vitesse, et a priori totalement compatible !
    mais aussi et surtout la commande -g qui va me permettre d'utiliser find moins rarement et surtout de pouvoir (enfin !) utiliser des PCRE pour chercher mes fichiers !

    Effectivement, ack-grep a été renommé en ack, et l'utilitaire qui s'appellait ack a du être renommé, je ne sais plus ce qu'était cet utilisateur, un truc de réseau si ma mémoire est bonne.

    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: Merci pour les découvertes

      Posté par  (site web personnel) . Évalué à 3. Dernière modification le 30 novembre 2021 à 17:38.

      la commande -g qui va me permettre d'utiliser find moins rarement

      ou plutôt plus rarement ? :-)

      Effectivement, avec ack on peut remplacer grep et find pour les utilisations les plus courantes. Evidemment ça ne remplace pas find avec ses multiples options mais pour trouver des fichiers avec une regex portant sur le nom, c'est impeccable.

  • # pdfgrep

    Posté par  (site web personnel) . Évalué à 3.

    Citons également pdfgrep dont les options sont similaires à celles de grep. Très pratique par exemple pour chercher une opération dans les PDF de vos relevés de compte bancaire :

    $ pdfgrep -ir paiement
    
  • # git grep

    Posté par  (site web personnel) . Évalué à 6. Dernière modification le 02 décembre 2021 à 12:44.

    Pour les utilisateurs de git on peut aussi citer git grep qui permet facilement de rechercher dans les fichiers trackés présentant un motif donné.

    Exemples du manuel

                   git grep 'time_t' -- '*.[ch]'
                       Looks for time_t in all tracked .c and .h files in the working directory and its subdirectories.
    
                   git grep -e '#define' --and \( -e MAX_PATH -e PATH_MAX \)
                       Looks for a line that has #define and either MAX_PATH or PATH_MAX.
    
                   git grep --all-match -e NODE -e Unexpected
                       Looks for a line that has NODE or Unexpected in files that have lines that match both.
    
                   git grep solution -- :^Documentation
                       Looks for solution, excluding files in Documentation.
    

    Adhérer à l'April, ça vous tente ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.