web-dev-qa-db-fra.com

Comment puis-je rechercher un motif multiligne dans un fichier?

Je devais trouver tous les fichiers contenant un motif de chaîne spécifique. La première solution qui me vienne à l’esprit est d’utiliser find avec le répertoire xargs grep :

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'

Mais si j'ai besoin de trouver des modèles qui couvrent plusieurs lignes, je suis bloqué parce que vanilla grep ne peut pas trouver de modèles multi-lignes.

104
Oli

J'ai donc découvert pcregrep ce qui signifie Perl expressions régulières compatibles GREP.

Par exemple, vous devez rechercher des fichiers où la variable '_name' est immédiatement suivie de la variable '_description':

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'

Astuce: vous devez inclure le caractère de saut de ligne dans votre modèle. Selon votre plate-forme, il peut s'agir de '\ n',\r ','\r\n ', ...

92
Oli

Pourquoi ne pas aller pour awk :

awk '/Start pattern/,/End pattern/' filename
81
Amit

Voici l'exemple utilisant GNU grep :

grep -Pzo '_name.*\n.*_description'

-z/--null-data Traite les données d'entrée et de sortie comme des séquences de lignes.

Voir aussi ici

65
ayaz

grep -P utilise également libpcre, mais much est plus largement installé. Pour trouver une section title complète d'un document HTML, même s'il s'étend sur plusieurs lignes, vous pouvez utiliser ceci:

grep -P '(?s)<title>.*</title>' example.html

Depuis que le projet PCRE s’applique à la norme Perl, utilisez la documentation Perl pour référence:

20
bukzor

Voici un exemple plus utile:

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html

Il recherche la balise de titre dans un fichier html même s'il s'étend sur 5 lignes.

Voici un exemple de lignes illimitées:

pcregrep -Mi "(?s)<title>.*</title>" example.html 
14
Oli

Avec chercheur d'argent :

ag 'abc.*(\n|.)*efg'

Les optimisations de vitesse du chercheur d'argent pourraient éventuellement briller ici.

7
Shwaydogg

Vous pouvez utiliser l'alternative grep sift ici (disclaimer: je suis l'auteur).

Il prend en charge la correspondance multiligne et limite la recherche à des types de fichiers spécifiques prédéfinis:

sift -m --files '* .py' 'YOUR_PATTERN'

(recherchez dans tous les fichiers * .py le motif de regex multiligne spécifié)

Il est disponible pour tous les principaux systèmes d'exploitation. Jetez un coup d’œil à la page exemples pour voir comment il est possible d’extraire des valeurs multilignes d’un fichier XML.

4
svent

Cette réponse pourrait être utile:

Regex (grep) pour la recherche multiligne nécessaire

Pour rechercher récursivement, vous pouvez utiliser les indicateurs -R (récursif) et --include (modèle GLOB). Voir:

Utilisez la syntaxe grep --exclude/- include pour ne pas passer par grep par le biais de certains fichiers

3
albfan
Perl -ne 'print if (/begin pattern/../end pattern/)' filename
2
pbal

Utilisation de ex/vi editor et option globstar (syntaxe similaire à awk et sed):

ex +"/string1/,/string3/p" -R -scq! file.txt

aaa est votre point de départ et bbb est votre texte de fin.

Pour effectuer une recherche récursive, essayez:

ex +"/aaa/,/bbb/p" -scq! **/*.py

Remarque: pour activer la syntaxe **, exécutez shopt -s globstar (Bash 4 ou zsh).

1
kenorb

@Marcin: Awk exemple non gourmand:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename
0
Martin