web-dev-qa-db-fra.com

sed: mon motif peut-il contenir un caractère "n'est pas"? Comment puis-je dire "n'est pas X"?

Comment dire "n'est pas" un certain caractère dans sed?

35
KRB
[^x]

Il s'agit d'une classe de caractères qui accepte n'importe quel caractère à l'exception de x.

47
Tom Zych

Pour ceux non satisfaits de la réponse sélectionnée selon commentaire de Johnny .

'su [^ x]' fera correspondre 'sum' et 'Sun' mais pas 'su'.

Vous pouvez dire à sed de not faire correspondre les lignes avec x en utilisant la syntaxe ci-dessous:

sed '/x/! s/su//' file

Voir la réponse de kkeller pour un autre exemple.

10

Il existe deux interprétations possibles de votre question. Comme d'autres l'ont déjà souligné, [^x] correspond à un seul caractère qui n'est pas x. Mais une chaîne vide n'est pas non plus x, donc peut-être cherchez-vous [^x]\|^$.

Aucune de ces réponses ne s'étend aux séquences multi-caractères, ce qui est généralement ce que les gens recherchent. Vous pourriez minutieusement construire quelque chose comme

[^s]\|s\($\|[^t]\|t\($\|[^r]\)\)\)

pour composer une expression régulière qui ne correspond pas à str, mais une solution beaucoup plus simple dans sed consiste à supprimer toute ligne qui ne correspond à str, puis gardez le reste;

sed '/str/d' file

Perl 5 a introduit un moteur regex beaucoup plus riche, qui est donc standard en Java, PHP, Python, etc. Parce que Perl prend en charge utilement un sous-ensemble de syntaxe sed, vous pourriez probablement convertir un simple script sed à Perl pour arriver à utiliser une fonctionnalité utile de ce dialecte regex étendu, comme les assertions négatives:

Perl -pe 's/(?:(?!str).)+/not/' file

remplacera une chaîne qui n'est pas str par not. Le (?:...) est un groupe non capturant (contrairement à de nombreux dialectes sed, une parenthèse non échappée est un métacaractère en Perl) et (?!str) est une assertion négative; le texte immédiatement après cette position dans la chaîne ne doit pas être str pour que l'expression régulière corresponde. Le + répète ce modèle jusqu'à ce qu'il ne corresponde pas. Remarquez comment l'assertion doit être vraie à chaque position de la correspondance, nous faisons donc correspondre un caractère à la fois avec . (les débutants se trompent souvent et n'affirment par erreur qu'au début d'un modèle plus long, qui pourrait cependant correspondre à str quelque part à l'intérieur, conduisant à une "fuite").

5
tripleee

D'après ma propre expérience, et l'article ci-dessous le confirme, sed ne prend pas en charge la négation régulière des expressions rationnelles en utilisant "^". Je ne pense pas que sed ait une méthode de négation directe ... mais si vous consultez le post ci-dessous, vous verrez quelques solutions. Regex Sed et négation de la sous-chaîne

1
A Beckler