Modèle multiligne Grep

13

Comment rechercher une phrase sur plusieurs lignes? Par exemple, laisse l'expression "mon thé glacé" puis il peut être enveloppé dans des fichiers texte:

as js skdfh dfh djh sf my
ice tea.

grep ne correspondra pas car il y a une nouvelle ligne entre les deux. Comment puis-je les assortir? Un autre modèle multiligne seraitpattern1_\n_pattern2

Je sais que la façon la plus simple de faire de l'ATM est juste de grep pour une partie par exemple juste de la glace avec le drapeau -A2 -B2 et ensuite dans cette sortie againg pour par exemple le thé. Mais c'est très fastidieux. Je suis donc intéressé par la façon de résoudre ce problème.

math
la source
1
doublon
intersite

Réponses:

16

Vous pouvez installer pcregrep(disponible dans la plupart des dépôts distro) - qui est grep en utilisant la bibliothèque pcre , qui fait "des expressions régulières compatibles Perl". Il a une option de ligne de commande -Mqui vous permet de faire des recherches multilignes - à partir de la page de manuel :

"La sortie de n'importe quelle correspondance peut être composée de plusieurs lignes."

Donc tu pourrais faire

pcregrep -M 'my\s+ice\s+tea' filename

L' \sespace est, qui correspondra \net \ren mode multiligne, en plus des espaces blancs normaux. Vous pouvez également faire correspondre directement le caractère de nouvelle ligne, vous pouvez donc

pcregrep -M 'pattern1_\n_pattern2' filename
Hamish Downer
la source
+1 sympa. Je n'en ai jamais entendu parler, mais je l'ai essayé et ça marche comme un charme!
DaveParillo
Ne fait pas de grep -Emotifs pcre?
Daenyth
3
@Daenyth grep -E la plupart du temps signifie simplement que vous pouvez utiliser ?, +, {, |, (et )leur sens habituel regex sans avoir à un \ devant, comme vous le faites si vous utilisez grep standard. grep 'hello\s\+world' fileEst donc équivalent à grep -E 'hello\s+world' file. Il ne fait pas PCRE. Il y a grep -Pdes expressions régulières pour perl, mais c'est expérimental (selon la page de manuel) et je pense que c'est un peu différent de pcregrep ...
Hamish Downer
1
Oui, je pensais à -Pquand j'ai dit -E, mais je ne savais pas que c'était différent.
Daenyth
3

Je ferais probablement une recherche en utilisant vimla :vimgrepcommande de. Cela fonctionne d'une manière vaguement similaire à celle de grepmais prend en charge les RE et les chemins vim.

Fondamentalement, vous exécutez quelque chose comme :vimgrep 'pattern1\npattern2' path/**pour une recherche récursive, puis tapez :copenpour afficher une fenêtre plus petite contenant une liste de correspondances.

vimLes RE peuvent faire presque tout ce que les PCRE peuvent faire, mais ils ont évolué séparément de la lignée d'expressions régulières perl, donc la plupart des choses avancées fonctionnent différemment. Leur fonctionnalité de base ressemble plus à celle des RE de base, mais ils ont quelques ajouts astucieux que les PCRE n'offrent pas.

Je ne sais pas s'il est possible :vimgrepde cracher des données comme grepça; Je n'ai essayé que de l'utiliser pour naviguer à l'intérieur vim.

:help vimgrepde l'intérieur vimpour plus d'informations; :help pattern.txtpour plus d'informations sur les vimRE; pour plus d'informations sur les chemins voir :help wildcards.

intuition
la source
Soyez prudent - ce n'est pas entièrement portable car il se comportera différemment sur différentes plates
Daenyth
1
@Daenyth: voulez-vous dire sous l'influence de différents .vimrc? Il devrait être plus portable que greppar rapport au système d'exploitation: vimn'a pas de "saveur POSIX", et fonctionne plus ou moins à l'identique même sous Windows. .................................................. ........................... Il est possible d'ajouter des qualificatifs pour s'assurer par exemple que la bonne quantité de "magie" est utilisée sur le RE, bien que si je comprends bien, il existe une règle stricte non écrite pour laisser cette option de côté.
intuition
Je ne l'ai pas utilisé moi-même, mais apparemment, il utilise un backend différent sur Windows ( find.exeau lieu de grep). Il y avait une autre question au cours des dernières semaines qui avait ce problème.
Daenyth
1
@Daenyth: Pensez-vous à :vimgrepou :grep? De :help grep: "L'avantage du grep interne [ie :vimgrep] est qu'il fonctionne sur tous les systèmes et utilise les puissants modèles de recherche Vim."
intuition
1
Ah, ça doit être ça. J'ai confondu les deux.
Daenyth
2

Grep ne fonctionne que sur une ligne à la fois, mais vous pouvez utiliser awk pour imprimer des lignes correspondant à une gamme de motifs:

cat file | awk '/foo/,/bar/'

il correspondrait à n'importe quoi, pas seulement à des sauts de ligne entre les deux modèles

DaveParillo
la source
0

Pour tirer le meilleur parti d'Unix, vous devez profiter des tuyaux. Vous pouvez le faire en clair à l' grepaide de tuyaux (pas besoin de tee):

$ grep -A1 "pattern1" file.txt |  grep "pattern2"

Ce que je ne considérerais pas comme fastidieux.

Baruch
la source
Je pense que c'est sujette aux erreurs, car entre pattern1 et pattern2 peut exister pattern3 qui pourrait ne pas être ce que vous recherchez. Vous devez donc contrôler chaque coup manuellement.
math