Prenez le script suivant:
#!/bin/sh sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Si j'essaie d'exécuter ceci dans sh
( dash
ici), cela va échouer à cause des parenthèses, qui doivent être échappées. Mais je n'ai pas besoin d'échapper aux backslashes eux-mêmes (entre les octets, ou dans le \s
ou \1
). Quelle est la règle ici? Qu'en est-il quand je dois utiliser {...}
ou [...]
? Y a-t-il une list de ce que je fais et n'ai pas besoin de m'échapper?
Il y a deux niveaux d'interprétation ici: le shell, et sed.
Dans le shell, tout ce qui se trouve entre guillemets simples est interprété littéralement, à l'exception des guillemets simples eux-mêmes. Vous pouvez effectivement avoir une seule guillemets entre guillemets simples en écrivant '\''
(guillemet simple fermé, guillemet simple littéral, guillemet simple ouvert).
Sed utilise des expressions régulières de base . Dans un BRE, les caractères $.*[\]^
Doivent être précédés d'une barre oblique inverse, sauf dans les jeux de caractères ( […]
). Lettres, numbers et (){}+?|
ne doit pas être cité (vous pouvez vous en passer en citant certaines de ces implémentations). Les suites \(
, \)
, \n
et dans certaines implémentations \{
, \}
, \+
, \?
, \|
et d'autres barres obliques inverses + caractères alphanumériques ont des significations particulières. Vous pouvez vous en sortir sans citer $^]
dans certaines positions de certaines implémentations.
En outre, vous avez besoin d'une barre oblique inverse avant /
si elle doit apparaître dans la regex. Vous pouvez choisir un autre caractère comme délimiteur en écrivant par exemple s~/dir~/replacement~
ou \~/dir~p
; vous aurez besoin d'une barre oblique inverse avant le délimiteur si vous souhaitez l'inclure dans le BRE. Si vous choisissez un caractère qui a une signification particulière dans un BRE et que vous voulez l'inclure littéralement, vous aurez besoin de trois barres obliques inverses; Je ne recommand pas cela.
En résumé, pour sed 's/…/…/'
:
'\''
pour finir avec un guillemet simple dans l'expression rationnelle. $.*/[\]^
Et seulement ces caractères. Dans le text de rlocation:
&
et \
besoin d'être cité, de même que le délimiteur (habituellement /
) et les returns à la ligne. \
suivi d'un chiffre a une signification particulière. \
suivi d'une lettre a une signification spéciale (caractères spéciaux) dans certaines implémentations, et \
suivi d'un autre caractère signifie \c
ou c
selon l'implémentation. sed 's/…/…/'
), utilisez '\''
pour mettre un guillemet simple dans le text de rlocation. Si le text regex ou de rlocation provient d'une variable shell, callbackez-vous que
\n
; &
, \
et les returns doivent être cités; sed -e "s/$BRE/$REPL/"
Le problème que vous rencontrez n'est pas dû à l'interpolation de shell et aux évasements – c'est parce que vous essayez d'utiliser la syntaxe d'expression régulière étendue sans passer l'option -r
ou --regexp-extended
.
Changez votre ligne sed de
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
à
sed -r 's/(127\.0\.1\.1)\s/\1/' [some file]
et cela fonctionnera comme je crois que vous avez l'intention.
Par défaut sed utilise des expressions régulières de base (pensez au style grep), ce qui nécessiterait la syntaxe suivante:
sed 's/\(127\.0\.1\.1\)[ \t]/\1/' [some file]
À less que vous vouliez interpoler une variable shell dans l'expression sed, utilisez des guillemets simples pour l'expression entière car ils font que tout ce qui se trouve entre eux est interprété tel quel, y compris les barres obliques inversées.
Donc, si vous voulez sed voir s/\(127\.0\.1\.1\)\s/\1/
mettre des guillemets autour et le shell ne touchera pas les parenthèses ou les antislashs. Si vous avez besoin d'interpoler une variable shell, mettez uniquement cette partie entre guillemets doubles. Par exemple
sed 's/\(127\.0\.1\.1\)/'"$ip"'/'
Cela vous évitera de vous callbacker quels métacaractères de shell ne sont pas échappés par des guillemets doubles.