2009-07-17 7 views
2

Disons que j'ai une expression régulière qui fonctionne correctement pour trouver toutes les URL dans un fichier texte:Comment obtenir l'inverse d'une expression régulière?

(http://)([a-zA-Z0-9\/\.])* 

Si ce que je veux est pas les URL, mais l'inverse - tout autre texte à l'exception des URL - est -il une modification facile à faire pour l'obtenir?

+1

Vous devez inclure un lien vers votre question d'origine (http://stackoverflow.com/questions/1140921/regex-to-strip-out-image-urls) pour le contexte. – Lee

Répondre

4

Si pour une raison quelconque, vous avez besoin d'une solution de regex seule, essayez ceci:

((?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%]))|\A(?!http://[a-zA-Z0-9\/\.#?/%])).+?((?=http://[a-zA-Z0-9\/\.#?/%])|\Z) 

j'ai développé l'ensemble des caractères d'URL un peu ([a-zA-Z0-9\/\.#?/%]) pour inclure quelques unes importantes , mais ceci n'est nullement destiné à être exact ou exhaustif.

Le regex est un peu d'un monstre, donc je vais essayer de le décomposer:

(?<=http://[a-zA-Z0-9\/\.#?/%]+(?=[^a-zA-Z0-9\/\.#?/%]) 

La première potion correspond à la fin d'une URL. http://[a-zA-Z0-9\/\.#?/%]+ correspond à l'URL elle-même, tandis que (?=[^a-zA-Z0-9\/\.#?/%]) affirme que l'URL doit être suivie d'un caractère non-URL afin que nous sommes sûrs que nous sommes à la fin. Un lookahead est utilisé pour que le caractère non-URL soit recherché mais pas capturé. Le tout est enveloppé dans un lookbehind (?<=...) pour le chercher comme la limite du match, encore une fois sans capturer cette partie.

Nous voulons également faire correspondre une non-URL au début du fichier. \A(?!http://[a-zA-Z0-9\/\.#?/%]) correspond au début du fichier (\A), suivi d'une recherche négative pour s'assurer qu'il n'y a pas d'URL qui se cache au début du fichier. (Cette URL vérification est plus simple que la première parce que nous avons seulement besoin du début de l'URL, et non pas la chose.)

Ces deux contrôles sont mis entre parenthèses et OR « d ainsi que le caractère |. Après cela, .+? correspond à la chaîne que nous essayons de capturer.

Ensuite, nous arrivons à ((?=http://[a-zA-Z0-9\/\.#?/%])|\Z). Ici, nous vérifions le début d'une URL, encore une fois avec (?=http://[a-zA-Z0-9\/\.#?/%]). La fin du fichier est également un très bon signe que nous avons atteint la fin de notre match, donc nous devrions chercher cela aussi, en utilisant \Z. De même que pour un premier grand groupe, nous l'enveloppons entre parenthèses et OR les deux possibilités ensemble.Le symbole | requiert la parenthèse car sa précédence est très faible, vous devez donc indiquer explicitement les limites du OR.

Cette expression régulière repose fortement sur des assertions de largeur nulle (les ancres \A et \Z et les groupes de recherche). Vous devriez toujours comprendre une regex avant de l'utiliser pour quelque chose de sérieux ou permanent (sinon vous pourriez attraper un cas de perl), donc vous voudrez peut-être vérifier Start of String and End of String Anchors et Lookahead and Lookbehind Zero-Width Assertions.

Corrections bienvenue, bien sûr!

+0

Je vois que vous avez pris cela comme la réponse acceptée. Merci! Je tiens à réitérer mon avertissement sur les expressions rationnelles complexes, cependant. Documentez-le bien si vous ou quelqu'un d'autre lisez le code plus tard. De plus, [a-zA-Z0-9 \/\. #? /%] Peut être changé en [a-zA-Z0-9 /.#?%] - vous (habituellement) n'avez pas besoin d'échapper symboles à l'intérieur d'un groupe de caractères. Vous pouvez également essayer https?: // au lieu de http: //, et éventuellement d'autres protocoles, selon vos besoins. N'oubliez pas de consulter http://www.regular-expressions.info/, comme suggéré par superjadex12. – WCWedin

7

Vous pouvez simplement rechercher et remplacer tout ce qui correspond à l'expression régulière par une chaîne vide, par ex. En Perl s/(http:\/\/)([a-zA-Z0-9\/\.])*//g

Cela vous donnerait tout dans le texte d'origine, sauf les sous-chaînes qui correspondent à l'expression régulière.

+0

Donc, après avoir remplacé toutes les correspondances, si la longueur de la chaîne testée n'est pas zéro, alors votre regex invert est vrai. C'est exactement la logique dont j'avais besoin, pas la construction d'une regex inversée. merci dmcer :) – Exter

1

Si je comprends bien la question, vous pouvez utiliser search/replace ... juste joker autour de votre expression et ensuite substituer la première et la dernière partie.

s/^(.*)(your regex here)(.*)$/$1$3/ 
+1

Cela ne fera que supprimer un match: le dernier. Et très inefficacement, aussi. –

0

je ne suis pas sûr si cela fonctionnera exactement comme vous avez l'intention, mais il pourrait aider: Tout ce que vous placez dans les crochets [] seront comparés. Si vous mettez^dans la parenthèse, c'est-à-dire [^ a-zA-Z0-9 /.] Cela correspondra à sauf ce qui est entre parenthèses.

http://www.regular-expressions.info/