Supposons que j'ai un fichier contenant plusieurs occurrences de StringA et StringB. Je souhaite remplacer toutes les occurrences de StringA par StringB et (simultanément) toutes les occurrences de StringB par StringA.
En ce moment, je fais quelque chose comme
cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'
Le problème avec cette approche est qu'elle suppose que StringC n'apparaît pas dans le fichier. Bien que ce ne soit pas un problème dans la pratique, cette solution semble toujours sale - c'est-à-dire qu'elle ressemble à une opportunité d'apprendre plus de magie Unix. 🙂
Réponse acceptée :
Si StringB
et StringA
ne peut pas apparaître sur la même ligne d'entrée, vous pouvez indiquer à sed d'effectuer le remplacement dans un sens, et n'essayer dans l'autre sens que s'il n'y avait aucune occurrence de la première chaîne recherchée.
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
Dans le cas général, je ne pense pas qu'il existe une méthode facile dans sed. Au fait, notez que la spécification est ambiguë si StringA
et StringB
peuvent se chevaucher. Voici une solution Perl, qui remplace l'occurrence la plus à gauche de l'une ou l'autre des chaînes, et se répète.
<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
s/(StringA|StringB)/$r{$1}/ge'
Si vous voulez vous en tenir aux outils POSIX, awk est la voie à suivre. Awk n'a pas de primitive pour les remplacements paramétriques généraux, vous devez donc créer la vôtre.
<file.txt awk '{
while (match($0, /StringA|StringB/)) {
printf "%s", substr($0, 1, RSTART-1);
$0 = substr($0, RSTART);
printf "%s", /^StringA/ ? "StringB" : "StringA";
$0 = substr($0, 1+RLENGTH)
}
print
}'