Il semble par exemple
cat sed_data.txt | sed 's/\b[0-9]\{3\}\b/NUMBER/g'
que je dois échapper des caractères pour former une expression régulière. Dans ce cas, j'ai dû échapper à des accolades afin d'être interprété plusieurs fois.
Pourquoi? Je m'attendais à ce que tout soit un caractère regex à moins qu'il ne s'échappe. C'est le contraire.
11
s/regex//g
déjà une expression régulière et je m'attendrais à ce que ce soit du texte qui aurait besoin à échapperRéponses:
En effet,
sed
utilise les BREIX POSIX (Expressions régulières de base) par opposition aux ERE (Expressions régulières étendues) auxquelles vous êtes probablement habitué de Perl ou d'amis.Depuis la
sed(1)
page de manuel:Citation pertinente du lien ci-dessus:
Citation textuelle du commentaire de Craig Sanders :
la source
-r
ou--regexp-extended
. Ceci est utile si vous souhaitez éviter d'uglifier votre script sed avec un échappement excessif.sed
implémentations (quand elles prennent en charge les ERE, principalement les BSD) ont tendance à utiliser-E
pour cela à la place (ce qui est beaucoup plus logique puisque c'est la même option que pourgrep
. Pourquoi GNU ased
choisi-r
est un mystère pour moi).C'est pour des raisons historiques.
Regexp a été introduit pour la première fois dans Unix dans l'
ed
utilitaire au début des années 70. Bien queed
se fondait surqed
dont la mise en œuvre par les mêmes auteurs compris regexp plus complexe,ed
ne comprenait^
,$
,[...]
,.
,*
et\
d'échapper à tout ce qui précède.Désormais, lorsque le besoin d'avoir plus d'opérateurs s'est fait sentir, il fallait trouver un moyen de les introduire sans rompre la compatibilité descendante. Si un script utilisait la
s
ed
commande ass/foo() {/foo (var) {/g
pour remplacer toutes les instances defoo() {
withfoo(var) {
et que vous introduisiez un opérateur(
or{
, cela casserait ce script.Cependant, aucun script ne ferait l'affaire
s/foo\(\) {/foo\(var\) {/
, car c'est la même choses/foo() {/foo(var) {/
et il n'y avait aucune raison de s'échapper(
car il ne s'agissait pas d'un opérateur RE. Ainsi, l'introduction d'un nouvel opérateur\(
ou\{
n'interrompt pas la compatibilité descendante car il est très peu probable qu'il casse un script existant en utilisant l'ancienne syntaxe.C'est donc ce qui a été fait. Plus tard, a
\(...\)
été ajouté initialement uniquement pour que las
ed
commande fasse des choses commes/foo\(.\)/\1bar/
et plus tardgrep '\(.\)\1'
(mais pas des choses comme\(xx\)*
).Dans UnixV7 (1979, donc près d'une décennie plus tard), une nouvelle forme d'expressions régulières a été ajoutée dans le nouveau
egrep
et lesawk
utilitaires appelés expression régulière étendue (car ce sont de nouveaux outils, il n'y a pas de compatibilité descendante à rompre). Enfin, il a fourni les fonctionnalités disponibles dans l'ancien de Ken Thompsonqed
(opérateur d'alternance|
, regroupement(..)*
) et a ajouté quelques opérateurs comme+
et?
(mais n'avait pas la fonction backref des expressions régulières de base).Plus tard, les BSD ont ajouté
\<
et\>
(à la fois à BRE et à ERE), et SysV a ajouté\{
et\}
à BRE uniquement.Ce n'est que bien plus tard que
{
et}
ont été ajoutés à ERE, par une telle compatibilité descendante. Tout le monde ne l'a pas ajouté. Par exemple, GNUawk
jusqu'à la version 4.0.0 (2011) ne prenait pas en charge à{
moins d'être forcé en mode de conformité POSIX.quand GNU a
grep
été écrit au début des années 90, il a ajouté tous les goodies de BSD et SysV (comme\<
,{
) et au lieu d'avoir deux syntaxe regexp et moteur distincts pour BRE et ERE, a implémenté les mêmes opérateurs dans les deux, seuls les homologues BRE de(
,?
,{
,+
doivent être précédés d'une barre oblique inverse (pour être compatible avec d' autres implémentations BRE). C'est pourquoi vous pouvez le faire.\+
dans GNUgrep
(bien que ce ne soit pas POSIX ou pris en charge par d'autres implémentations) et vous pouvez le faire(.)\1
dans GNUegrep
(bien que ce ne soit pas POSIX ou pris en charge par de nombreuses autres implémentations, y compris GNUawk
).L'ajout d'
\x
opérateurs n'est pas le seul moyen d'ajouter plus d'opérateurs d'une manière rétrocompatible. Par exemple,perl
utilisé(?...)
. C'est toujours rétrocompatible avec les ERE car il(?=...)
n'est pas valide dans les ERE, de même pour.*?
.vim
pour des opérateurs similaires l'ont fait différemment en introduisant\@=
ou.\{-}
par exemple.la source