Double Possible:
Comment puis-je rechercher une multiligne motif dans un fichier ? Utilisation pcregrepJe suis à court d'un
grep
trouver tout *.fichier sql qui a le motselect
suivi par le motcustomerName
suivi par le motfrom
. Cette instruction select peut s'étendre sur plusieurs lignes et peut contenir des tabulations et retours à la ligne.J'ai essayé quelques variations sur les points suivants:
$ grep -liIr --include="*.sql" --exclude-dir="\.svn*" --regexp="select[a-zA-Z0- 9+\n\r]*customerName[a-zA-Z0-9+\n\r]*from"
Cela, toutefois, ne s'exécute jamais. Quelqu'un peut m'aider avec la syntaxe correcte s'il vous plaît?
Réponses
Trop de publicités?Sans avoir besoin d'installer le grep variante pcregrep, vous pouvez le faire de plusieurs lignes de recherche avec grep.
$ grep -Pzo "(?s)^(\s*)\N*main.*?{.*?^\1}" *.c
Explication:
-P
activer perl-regexp pour grep (une puissante extension de régulièrement des extensions)
-z
supprimer le saut de ligne à la fin de la ligne, subtituting pour caractère null. C'est, grep sait où la fin de la ligne, mais voit l'entrée comme une grande ligne.
-o
imprimer uniquement de la correspondance. Parce que nous utilisons -z
, le fichier entier est comme une seule grande ligne, donc si il ya un match, le fichier sera imprimé; de cette manière, il n'allons pas le faire.
Dans regexp:
(?s)
activer PCRE_DOTALL
, ce qui signifie qu' .
trouve n'importe quel caractère ou de saut de ligne
\N
trouver de tout, sauf de saut de ligne, même avec PCRE_DOTALL
activé
.*?
trouver .
dans nongreedy mode, qui est, s'arrête dès que possible.
^
trouver début de ligne
\1
référence arrière à premier groupe (\s*
) C'est d'essayer de trouver de même indentation de la méthode
Comme vous pouvez l'imaginer, cette recherche imprime la méthode main dans un C (*.c
) du fichier source.
Je ne suis pas très bon dans grep. Mais votre problème peut être résolu à l’aide de la commande AWK . Il suffit de voir
Le code ci-dessus entraînera de la première occurrence de jusqu'à la première séquence de
. Maintenant, vous devez vérifier si les déclarations retournées ont `` ou non. Pour cela, vous pouvez rediriger le résultat. Et awk ou grep peut réutiliser.
Votre problème fondamental est qu' grep
fonctionne une ligne à la fois - de sorte qu'il ne peut pas trouver une instruction SELECT, réparties à travers les lignes.
Votre deuxième problème est que la regex que vous utilisez n'aura pas à composer avec la complexité de ce qui peut apparaître entre les SÉLECTIONNER et DE - en particulier, il omet les virgules, les points (périodes) et les blancs, mais aussi des citations et tout ce qui peut être à l'intérieur d'une chaîne de caractères entre guillemets.
Je serais probablement aller avec un Perl-base de solution, ayant Perl lire "paragraphes" à un moment et en appliquant une regex. L'inconvénient est d'avoir à traiter avec la recherche récursive - il existe des modules pour le faire, bien sûr, y compris le noyau du module File::Find.
Dans les grandes lignes, pour un seul et même fichier:
$/ = "\n\n"; # Paragraphs
while (<>)
{
if ($_ =~ m/SELECT.*customerName.*FROM/mi)
{
printf file name
go to next file
}
}
Qui doit être enveloppé dans un sous c'est alors invoquée par les méthodes de File::Find.
N’est pas `` uniquement pour la recherche de la seule ligne ? Cette question est peut-être utile pour vous : Comment puis-je Rechercher un modèle multiligne dans un fichier ?
En dehors de l’expression régulière, vous pouvez regarder dans l' accusé de réception, qui exclut automatiquement les répertoires .svn pour vous, et qui peut limiter à seulement les fichiers .sql--SQL.