web-dev-qa-db-fra.com

Notepad ++ capture regex group

J'ai un tel fichier txt:

ххх.prontube.ru
salo.ru
bbb.antichat.ru
yyy.ru
xx.bb.prontube.ru
zzz.com
srfsf.jwbefw.com.ua

Essayer de supprimer tous les sous-domaines avec une telle expression régulière:

Find:    .+\.((.*?)\.(ru|ua|com\.ua|com|net|info))$
Replace with: \1

Recevoir:

prontube.ru
salo.ru
antichat.ru
yyy.ru
prontube.ru
zzz.com
com.ua

Pourquoi la dernière ligne devient com.ua au lieu de jwbefw.com.ua?

47
pnslg

Cela fonctionne sans regarder autour:

Rechercher: [a-zA-Z0-9-.]+\.([a-zA-Z0-9-]+)\.([a-zA-Z0-9-]+)$ Remplacer: \1\.\2

Il trouve quelque chose avec au moins 2 points et uniquement des lettres, des chiffres et des tirets après les deux derniers points; puis il le remplace par les 2 dernières parties. Plus intuitif, à mon avis.

Il se passe quelque chose de drôle avec ce premier xxx. Il ne semble pas être en simple ASCII. Pour cette question, je vais supposer que c'est juste quelque chose de drôle avec ce site et non représentatif de vos données réelles.

Incorrect

Fait intéressant, j'avais précédemment une réponse incorrecte ici qui a accumulé beaucoup de votes positifs. Je pense donc que je devrais le conserver:

Rechercher: [a-zA-Z0-9-]+\.([a-zA-Z0-9-]+)\.(.+)$ Remplacer: \1\.\2

Il trouve juste un nom d'hôte avec au moins 2 points, puis le remplace par tout après le premier point.

48
jpmc26

Le .+ partie correspond autant que possible. Essayez d'utiliser .+? à la place, et il capturera le moins possible, permettant à com.ua option pour correspondre.

9
.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$

Cette réponse utilise toujours les noms de domaine spécifiques que la question d'origine examinait. Comme certains TLD (domaines de premier niveau) ont une période et que vous pourriez théoriquement avoir une liste comprenant plusieurs sous-domaines, la mise en liste blanche du TLD dans l'expression régulière est une bonne idée si cela fonctionne avec votre ensemble de données. Les deux réponses actuelles (de 2013) ne géreront pas correctement la différence entre "xx.bb.prontube.ru" et "srfsf.jwbefw.com.ua".

Voici une explication rapide des raisons pour lesquelles l'expression rationnelle originale de ce psnig ne fonctionne pas comme prévu:
Le + Est gourmand. .+ Zippera complètement à droite à la fin de la ligne pour tout capturer, puis remontera (vers la gauche) à la recherche d'une correspondance à partir d'ici:

(ru|ua|com\.ua|com|net|info)

Avec srfsf.jwbefw.com.ua le moteur d'expression régulière échouera d'abord à correspondre à a, puis il déplacera le jeton d'un endroit vers la gauche pour regarder "ua" À ce stade , ua du regex (la deuxième option) est une correspondance.

Le moteur ne cherchera pas à trouver "com.ua" car ".ua" répondait à cette exigence.

La réponse de Niet the Dark Absol dit que l'expression régulière est "paresseuse"
.+? Correspondra à n'importe quel caractère (au moins un), puis tentera de trouver la partie suivante de l'expression régulière. Si cela échoue, il fera avancer le jeton, .+ Correspondant à un caractère de plus, puis évaluant à nouveau le reste de l'expression régulière.
Le. +? finira par consommer: srfsf.jwbefw avant de faire correspondre la période, puis de faire correspondre com.ua.

Mais l'implantation de ? Crée également des problèmes.

L'ajout du point d'interrogation fait cela en premier. + Paresseux, mais fait ensuite correspondre group1 bb.prontube.r au lieu de prontube.r

C'est parce que cette première période après le bb correspondra, puis à l'intérieur du groupe 1 (.*?) Correspondra bb.prontube. avant \.(ru|ua|com\.ua|com|net|info))$ correspond à . r

Pour éviter cela, changez ce troisième groupe de (.*?) En ([\w-]*?) Afin qu'il ne capture pas . uniquement des lettres et des chiffres, ou un tiret.

expression régulière résultante:
.+?\.(([\w-])*?\.(ru|ua|com\.ua|com|net|info))$

Notez que vous n'avez pas besoin de capturer d'autres groupes que le premier. Ajouter?: Rend les options TLD non capturantes.

dernier changement:
.+?\.([\w-]*?\.(?:ru|ua|com\.ua|com|net|info))$

1
davidlc