ack 2.0

Posté par (page perso) . Édité par Davy Defaud, BAud, Nÿco, Florent Zara et barmic. Modéré par tuiu pol. Licence CC by-sa
Tags :
40
23
avr.
2013
Ligne de commande

La commande ack est un équivalent à grep, optimisé pour parcourir les répertoires hétérogènes de code source. Par défaut, si aucun fichier n’est donné en paramètre, ack parcourt le dossier courant.

Publiée sous Artistic License 2.0, les principales nouveautés de cette version 2 sont :

  • Par défaut, et contrairement à la version 1.x, tous les fichiers, même ceux dont le type n’est pas connu, sont parcourus. Il est possible de revenir à l’ancien comportement avec l’option -k.
  • L’identification du type de fichier est améliorée, elle se base soit sur l’extension (.rb identifie un fichier de type Ruby), soit sur le nom (Rakefile identifie un fichier de type Ruby), soit sur le contenu du fichier (/#!.+ruby/ dans la première ligne d’un fichier identifie également un fichier de type de Ruby).
  • Les fichiers de configuration sont plus granulaires : /etc/ackrc est global au système, ~/.ackrc est spécifique à l’utilisateur et l’on peut avoir un fichier spécifique au projet courant.
  • L’option -x dit à ack de parcourir la liste de fichiers envoyée via stdin à la manière de xargs, ce qui permet d’écrire des commandes du genre git ls|ack --type=cpp -x foo.

Il est aussi possible d’écrire des greffons en Perl pour aller lire d’autres types de fichiers comme une archive ZIP ou un classeur ODF.

N. B. : Attention, sous Debian et Ubuntu, le logiciel s’appelle ack-grep (ack existant déjà). Le site officiel d’ack présente la méthode pour l’installer en tant que ack, qui est plus propre que celle décrite dans la page de manuel du paquet ack-grep (dans la dernière question de la FAQ).

Exemple d’utilisation qui va chercher dans les sources de LinuxFr.org les fichiers de type Ruby qui contiennent le mot « rédaction » :

Exemple d'utilisation d'ack

  • # Ag

    Posté par . Évalué à 9.

    Il y a également ag, qui est une ré-implémentation en C de ack:
    https://github.com/ggreer/the_silver_searcher

    C’est plus rapide que ack dans le cas généra, et aussi rapide que git grep dans les dossiers gérés par git par exemple.

  • # Performances

    Posté par . Évalué à 9.

    J'utilise actuellement un bête script qui wrappe find/grep. Grosso modo ça fini par faire une commande genre :
    find . \( -name "*.c" -o -name *.h \) -exec grep -n --color {} /dev/null \;

    J'ai donc testé ack qui me semblait être un remplacement intéressant. Le problème est qu'il est vraiment trop lent ! Dans mon cas de test je passe de 0.255s via find/grep à 1.401s pour ack (avec l'option -cc qui va bien). Soit près de 5 fois plus lent!

    Donc bon…

    Faudrait que je teste la version C du commentaire ci-dessus.

    • [^] # Re: Performances

      Posté par . Évalué à 7.

      Un billet intéressant de Christophe Blaess à ce sujet (les commentaires qui suivent sont intéressants aussi), cela pourrait te permettre de gagner encore un peu de performances :

      http://www.blaess.fr/christophe/2013/04/08/optimiser-les-recherches-recursives-avec-xargs/

      Pourquoi passe-tu /dev/null à grep ?

      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: Performances

        Posté par . Évalué à 10.

        grep affiche le nom du fichier source que s'il y en a plusieurs. Or find passe les fichiers 1 par 1 à grep. Du coup je lui file un second "fichier" pour qu'il m'affiche le nom du premier fichier.
        Le pire c'est que j'ai lu cette astuce dans un man de find!
        Les versions actuelles de grep ont une option -H qui remplace avantageusement le /dev/null. Mais les habitudes ont la peau dures…

    • [^] # Re: Performances

      Posté par (page perso) . Évalué à 1.

      Et en remplaçant l'appel à find par du **, est-ce plus lent, plus rapide ou pareil ? (dans la limite du nombre de fichiers accepté par le shell)

      • [^] # Re: Performances

        Posté par . Évalué à 4.

        Dans le liens que j'ai mis au dessus, il y a un commentaire qui en parle.

        Les problèmes des expansion de chemin étendus :

        • limite du nombre de fichiers (si tu veut travailler sur 80 000 fichiers tu aura une erreur)
        • le shell commence par calculer la liste des fichiers avant de lancer la commande (selon comment on se sert de find c'est plus lent avec les globings, notamment avec find + xargs)

        Avec zsh tu as zargs qui est un équivalent à xargs pour les globings, mais c'est super lent ! Je ne comprends pas pourquoi.

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Vraiment nécessaire ?

    Posté par (page perso) . Évalué à 6.

    J'ai testé Ack pendant un temps au boulot, mais j'ai trouvé ça trop lent.

    De manière générale, je créer un alias comme celui-ci :
    alias grep='grep --line-buffered --color=auto -s -P'

    Ensuite, pour sélectionner par type de fichier, je me fis aux extensions :
    find -name "*.py" | xargs grep 'Hello'

    De plus, je préfère comment Grep surligne le résultat.

    • [^] # Re: Vraiment nécessaire ?

      Posté par . Évalué à 6.

      Tu as aussi grep -r --include="*.py" pour éviter le find.

      • [^] # Re: Vraiment nécessaire ?

        Posté par (page perso) . Évalué à 1.

        C'est quasiment identique, mais plus général avec xargs. Voici ce que j'obtiens chez moi :

        Sachant que find -name "*.h" | wc -l donne 3711.

        Ex : time grep -r --include "*.h" 'include' . > /dev/null
        0.10s user 0.56s system 28% cpu 2.324 total

        Ex : time find -name "*.h" | xargs grep 'include' > /dev/null
        find -name "*.h" 0.04s user 0.08s system 11% cpu 1.004 total
        xargs grep 'include' > /dev/null 0.04s user 0.08s system 8% cpu 1.408 total
        Soit 2.4s.

        Ex : time find -name "*.h" -exec grep 'include' {} \; > /dev/null
        0.04s user 0.38s system 6% cpu 6.529 total

        • [^] # Re: Vraiment nécessaire ?

          Posté par . Évalué à 3.

          Et avec :

          time find -name "*.h" -exec grep 'include' {} \+ > /dev/null
          
          

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: Vraiment nécessaire ?

          Posté par . Évalué à 1.

          Pour ma part, je n'utilise ni la méthode avec "-exec", et n'étant pas familier de la méthode avec "xargs", j'ai toujours utilisé la commande suivante, toujours dans le but de minimiser les forks/exec de commande (ici, juste 2 commandes), en plus je trouve que c'est rapide à écrire :

          grep 'include' $(find -name "*.h")

          (les quotes autour de include ne sont pas nécessaires mais je les ai laissés pour ne pas vous perturber ;) )

          J'ai conscience que ma ligne de commande peut poser un problème en cas de trop grand nombre de fichiers retournés pas le "find".
          En tous cas je note le "+" utilisable avec "-exec", option que je ne connaissais pas.

  • # Couleur par défaut

    Posté par . Évalué à 4.

    Hello j'utilise un terminal ou le texte est sombre et le fond clair et la sortie de ack est illisible. Il y a-t'il un fichier couleur prévu pour ça et fournit par défaut avec ack ?

  • # ack-grep versus ack

    Posté par (page perso) . Évalué à 2. Dernière modification le 23/04/13 à 17:10.

    Le site officiel d'ack présente la méthode pour l'installer en tant que ack qui est plus propre que celle décrite dans la man du paquet ack-grep (dans la dernière question de la FAQ)

    Le man en question n'est pas propre au paquet debian/ubuntu mais vient directement du site officiel ack : http://beyondgrep.com/documentation/ack-2.02-man.html#why_is_it_called_ack_if_it_s_called_ack_grep. Faut leur signaler qu'ils ont une incohérence (et aussi faire un bug report chez debian pour qu'ils virent ça du man où ça ne devrait pas être).

  • # glimpse

    Posté par (page perso) . Évalué à 2.

    Quand on travaille sur un ensemble de code sources, il y a aussi l'outil glimpse. Elle nécessite d'avoir fait au préalable un glimpseindex pour constituer un fichier d'index et puis ensuite, on utilise glimpse comme egrep avec des résultats instantanés. La phase glimpseindex peut être mise en cron, du genre toutes les nuits.

Suivre le flux des commentaires

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