255 votes

Regex pour les chaînes ne se terminant pas par un suffixe donné

Je n'ai pas été capable de trouver une regex appropriée pour correspondre à n'importe quelle chaîne de caractères. no se terminant par une certaine condition. Par exemple, je ne veux pas correspondre à tout ce qui se termine par un a .

Cela correspond

b
ab
1

Cela ne correspond pas

a
ba

Je sais que la regex devrait se terminer par $ pour marquer la fin, bien que je ne sache pas ce qui devrait la précéder.

Editar : La question originale ne semble pas être un exemple légitime pour mon cas. Donc : comment gérer plus d'un personnage ? Disons que tout ce qui ne se termine pas par ab ?

J'ai réussi à résoudre ce problème en utilisant ce fil :

.*(?:(?!ab).).$

L'inconvénient de cette méthode est qu'elle ne correspond pas à une chaîne d'un seul caractère.

4voto

MatthewRock Points 713

La réponse acceptée est bonne si vous pouvez utiliser des solutions de rechange. Cependant, il existe également une autre approche pour résoudre ce problème.

Si nous regardons la regex largement proposée pour cette question :

.*[^a]$

Nous trouverons qu'il presque fonctionne. Il n'accepte pas une chaîne vide, ce qui peut être un peu gênant. Toutefois, il s'agit d'un problème mineur lorsqu'il s'agit d'un seul caractère. Cependant, si nous voulons exclure une chaîne entière, par exemple "abc", alors :

.*[^a][^b][^c]$

ne fera pas l'affaire. Il n'accepte pas l'ac, par exemple.

Il existe pourtant une solution simple à ce problème. Nous pouvons simplement dire :

.{,2}$|.*[^a][^b][^c]$

ou une version plus généralisée :

.{,n-1}$|.*[^firstchar][^secondchar]$ où n est la longueur de la chaîne que vous voulez interdire (pour abc c'est 3), et firstchar , secondchar ... sont le premier, le deuxième et le nième caractère de votre chaîne de caractères. abc ce serait a entonces b entonces c ).

Cela vient d'une simple observation qu'une chaîne de caractères qui est plus courte que le texte que nous n'interdisons pas ne peut pas contenir ce texte par définition. Nous pouvons donc soit accepter tout ce qui est plus court ("ab" n'est pas "abc"), soit tout ce qui est suffisamment long pour que nous l'acceptions mais sans la fin.

Voici un exemple de recherche qui supprimera tous les fichiers qui ne sont pas des .jpg :

find . -regex '.{,3}$|.*[^.][^j][^p][^g]$' -delete

1voto

tombert Points 111

La question est ancienne mais je n'ai pas trouvé de meilleure solution, je poste la mienne ici. Trouver tous les lecteurs USB mais ne pas lister les partitions ce qui permet de supprimer les "part[0-9]" des résultats. J'ai fini par faire deux grep, le dernier annule le résultat :

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -vE "part[0-9]*$"

Ce résultat sur mon système :

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

Si je ne veux que les partitions, je pourrais le faire :

ls -1 /dev/disk/by-path/* | grep -P "\-usb\-" | grep -E "part[0-9]*$"

Où je suis :

pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part1
pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0-part2

Et quand je le fais :

readlink -f /dev/disk/by-path/pci-0000:00:0b.0-usb-0:1:1.0-scsi-0:0:0:0

J'ai compris :

/dev/sdb

0voto

Bill Points 2753

Tout ce qui correspond à quelque chose se terminant par un --- .*a$ Donc, quand tu fais correspondre l'expression, tu annules la condition. ou alternativement, vous pouvez aussi faire .*[^a]$ donde [^a] signifie tout ce qui est not a

0voto

abalter Points 600

Si vous utilisez grep o sed la syntaxe sera un peu différente. Remarquez que le séquentiel [^a][^b] ne fonctionne pas ici :

balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n'
jd8a
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a]$"
8$fb
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^b]$"
jd8a
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a][^c]$"
jd8a
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^b]$"
q(c
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^a^c]$"
8$fb
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c]$"
jd8a
balter@spectre3:~$ printf 'jd8a\n8$fb\nq(c\n' | grep ".*[^b^c^a]$"

Pour info, je trouve les mêmes résultats dans Regex101 qui, je pense, est une syntaxe JavaScript.

Mauvais : https://regex101.com/r/MJGAmX/2
Bien : https://regex101.com/r/LzrIBu/2

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X