2016-03-17 2 views
2

Supposons que nous effectuions une recherche de motifs regex multilignes sur un tas de fichiers et que nous voulions extraire les correspondances de grep. Par défaut, les sorties grep sont séparées par des retours à la ligne, mais étant donné que nous effectuons des tracés multilignes, cela crée l'inconvénient que nous ne pouvons pas facilement extraire les correspondances individuelles.Comment rendre la sortie grep séparée par des caractères NULL?

Exemple

grep -rzPIho '}\n\n\w\w\b' | od -a 

En fonction des fichiers dans votre arborescence de fichiers, cela peut donner une sortie comme

0000000 } nl nl m y nl } nl nl i f nl } nl nl m 
0000020 y nl } nl nl m y nl } nl nl i f nl } nl 
0000040 nl m y nl 
0000044 

Comme vous pouvez le voir, nous ne pouvons pas partager sur les nouvelles lignes pour obtenir les résultats pour un traitement ultérieur , puisque les correspondances contiennent des caractères de nouvelle ligne eux-mêmes.

Ce qui ne fonctionne fonctionne pas

Maintenant, le --null (ou -Z) uniquement en association avec -l, ce qui rend grep seule liste des noms de fichiers au lieu de matches, donc cela ne suffit pas ici.

Notez qu'il ne s'agit pas d'un doublon de Is there a grep equivalent for find's -print0 and xargs's -0 switches?, car les exigences de cette question sont différentes, ce qui permet de répondre à l'aide de techniques alternatives.

Alors, comment pouvons-nous faire en sorte que cela fonctionne? Peut-être utiliser grep en conjonction avec d'autres outils?

+1

Je vais aller avec "vous ne pouvez pas" ici si 'grep' lui-même ne peut pas le faire pour vous (et qui dit que vous n'avez pas' NUL' dans vos données correspondantes pour commencer) . Vous avez abusé un peu de 'grep 'pour faire ce travail déjà. J'utiliserais la sortie 'od' (ou similaire) ou j'utiliserais un outil autre que' grep' pour contrôler mieux la sortie ('awk' ou' perl' ou autre chose). –

+0

Un tuple de nom de fichier, de décalage d'octet et de longueur de correspondance vous permettrait de collecter les correspondances réelles lorsque vous en aurez besoin. Je ne pense pas que ce soit faisable avec 'grep' mais l'implémenter en Python ou en Perl ne devrait pas être difficile. – tripleee

+0

Pouvez-vous ajouter un exemple de texte à votre question, et la sortie attendue? Je recommande également d'utiliser 'awk' pour cela. – miken32

Répondre

3

Je déposé cette question comme une demande de fonctionnalité dans la liste de diffusion bug GNU grep, et il semble y avoir un bug dans le code.

Il a été fixé et poussé à maîtriser, donc il sera disponible dans la prochaine version de GNU grep: http://git.savannah.gnu.org/cgit/grep.git/commit/?id=cce2fd5520bba35cf9b264de2f1b6131304f19d2

Pour résumer: ce patch veille à ce que le drapeau -z fonctionne non seulement en conjonction avec -l, mais aussi avec -o.

1

Ce qui me vient à l'esprit serait d'utiliser un séparateur de groupe, par exemple quelque chose comme:

grep -rzPIho '}\n\n\w\w\b' $FILE -H | sed "s/^$FILE:/\x0/" 
+0

Ouais, cela semble assez simple. Pas entièrement preuve si vous avez des fichiers très courts, mais +1. A besoin d'une logique supplémentaire lorsque vous faites plus de fichiers btw –

+0

Oui, ce n'est pas entièrement infaillible et doit être amélioré; cela dépend également du contenu du fichier. S'il vous plaît laissez-nous savoir si vous venez avec une meilleure solution: ^) – bufh

+0

Vérifier ma dernière réponse –

1

Voici une autre façon de le faire, ce qui devrait être plus à toute épreuve que ce @bufh affiché, mais est aussi plus compliqué et plus lent.

$ grep -rIZl '' --include='*.pl'| xargs -0 cat | dos2unix | tr '\n\0' '\0\n' \ 
     | grep -Pao '}\x00\x00\w\w\b' | tr '\0\n' '\n\0' | od -a 

Le dos2unix est évidemment nécessaire uniquement lorsque vous travaillez avec des fins de ligne Windows. Donc, la ligne de punch ici est que nous échangeons des octets nuls avec des retours à la ligne dans l'entrée, grep correspond sur nullbytes à la place et échange des choses.

0000000 } nl nl m y nul } nl nl i f nul } nl nl m 
0000020 y nul } nl nl m y nul } nl nl i f nul } nl 
0000040 nl m y nul 
0000044