utilisation de sed avec esperluette (&)

19

J'utilise sed pour trouver et remplacer des modèles dans les fichiers SAS que j'ai plutôt que de les modifier individuellement. Le problème est que j'essaie de remplacer les variables de macro et que lorsque j'utilise l'esperluette, il ne fonctionne pas correctement.

Here's my code:
sed -ie 's/user=&uid./user=&sysuserid./g' *_table_*.sas

chaque fois que j'exécute cette commande, elle semble s'ajouter et faire toutes sortes de choses géniales avec le texte original.

Question: Comment remplacer du texte contenant des esperluettes par la commande sed?

lucasdavis500
la source
6
&est un caractère spécial, il doit donc être échappé lorsqu'il est utilisé dans le RHS - dans votre cas, vous devez exécuter 's/user=&uid./user=\&sysuserid./g'bien que je soupçonne que vous devez également échapper le point dans le LHS pour correspondre à un point littéral afin que vous en ayez réellement besoin's/user=&uid\./user=\&sysuserid./g'
don_crissti
1
oui, «&» à droite signifie essentiellement «tout ce qui correspond à gauche», alors échappez-le avec «\». Vous devriez en faire la réponse, plutôt qu'un simple commentaire.
Edward Falk
je n'ai pas eu à échapper à la première période ... juste un
avertissement

Réponses:

25

&est spécial dans le texte de remplacement: cela signifie « toute la partie de l'entrée qui a été compensée par le modèle », donc ce que vous faites ici remplace user=&uidXavec user=user=&uidXsysuserid.. Pour insérer une esperluette réelle dans le texte de remplacement, utilisez\& .

Une autre chose qui semble erronée est que .dans le modèle de recherche représente n'importe quel caractère (sauf une nouvelle ligne), mais .à la fin du texte de remplacement est un point littéral. Si vous souhaitez remplacer uniquement la chaîne littérale user=&uid., protégez le .avec une barre oblique inverse.

sed -e 's/user=&uid\./user=\&sysuserid./g'

Si vous souhaitez remplacer un caractère et le conserver dans le résultat, placez le caractère dans un groupe et utilisez-le \1dans le remplacement pour faire référence à ce groupe.

sed -e 's/user=&uid\(.\)/user=\&sysuserid\1/g'

En fait, compte tenu de la répétition entre le texte original et le remplacement, vous devez quand même utiliser des groupes:

sed -e 's/\(user=&\)u\(id\.\)/\1sysuser\2/g'

c'est-à-dire «remplacer upar sysuserentre user=&et id.».

Gilles 'SO- arrête d'être méchant'
la source
pourriez-vous expliquer les groupes?
lucasdavis500
2
@ lucasdavis500 Un groupe identifie une partie du motif. Il est délimité par des parenthèses antislash. Par exemple, \(user=&\)est un modèle qui correspond user&et stocke la chaîne de correspondance en tant que groupe (groupe numéro 1 car c'est le premier groupe du modèle). Ensuite, dans le remplacement \1est remplacé par la chaîne stockée pour le groupe numéro 1.
Gilles 'SO- arrête d'être méchant'
voulez-vous dire que (utilisateur = &) stocke l'utilisateur = &, pas l'utilisateur &?
lucasdavis500
@ lucasdavis500 Je ne comprends pas votre commentaire. Le caractère =dans les expressions régulières et dans le texte de remplacement est synonyme de lui-même, donc user=&correspond uniquement user=&, et user=&dans le texte de remplacement, il est user=suivi de la partie de la ligne correspondant à l' expression régulière .
Gilles 'SO- arrête d'être méchant'
1
@ lucasdavis500 Le =personnage n'a pas de signification particulière. user=&dans le texte de remplacement produit user=suivi du texte original correspondant. user=\&dans le texte de remplacement produituser=&
Gilles 'SO- arrête d'être méchant'