Supongamos que tengo un archivo que contiene varias apariciones de StringA y StringB. Quiero reemplazar todas las apariciones de StringA con StringB y (simultáneamente) todas las apariciones de StringB con StringA.
En este momento, estoy haciendo algo como
cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'
El problema con este enfoque es que asume que StringC no aparece en el archivo. Si bien esto no es un problema en la práctica, esta solución todavía se siente sucia, es decir, se siente como una oportunidad para aprender más magia de Unix. 🙂
Respuesta aceptada:
Si StringB
y StringA
no puede aparecer en la misma línea de entrada, entonces puede decirle a sed que realice el reemplazo de una manera, y solo intente de la otra manera si no hubo ocurrencias de la primera cadena buscada.
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
En el caso general, no creo que haya un método fácil en sed. Por cierto, tenga en cuenta que la especificación es ambigua si StringA
y StringB
puede superponerse. Aquí hay una solución de Perl, que reemplaza la aparición más a la izquierda de cualquier cadena y se repite.
<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
s/(StringA|StringB)/$r{$1}/ge'
Si desea seguir con las herramientas POSIX, awk es el camino a seguir. Awk no tiene un primitivo para reemplazos parametrizados generales, por lo que debe crear el suyo propio.
<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
}'