Saltar la navegación

Comando s (substitute)

El comando s (substitute) es el más usado con sed y se utiliza para llevar a cabo una operación de búsqueda y sustitución. Su sintaxis es la siguiente:

s/expresión regular a buscar/texto de sustitución/[modificadores]

El comando s intenta casar la expresión regular dentro de la zona de trabajo, y si lo consigue, el trozo de texto que ha casado (el más grande siempre) lo sustituye por el texto del segundo argumento. En la zona de trabajo podría haber varíos trozos de texto que casaran con la expresión regular, solo se sustituirá la primera coincidencia, a menos que explícitamente se indique la sustitución de todas las coincidencias, lo cual se haría a través de un modificador.

Es posible no especificar la expresión regular a buscar (//), con lo que se estaría haciendo referencia a la expresión regular del ámbito del comando s, y si no hubiera ámbito o este no fuera una expresión regular, entonces se mostraría un mensaje de error. Veamos el siguiente ejemplo:

$ sed '/u/ s//-/' f g
-no
dos
tres
c-atro
$ sed 's//-/' f g
sed: -e expresión #1, carácter 0: no hay una expresión regular previa

Se puede observar que la expresión regular que se está buscando y que luego se sustituye por un guión es la expresión regular del ámbito.

El texto de sustitución puede incluir retroreferencias (\1 - \9) si se usan subexpresiones en la expresión regular. También, es posible incluir el carácter & o \0, pudiéndose usar una o varias veces, para referirnos al texto completo que ha casado con la expresión regular.

$ echo '<i id="saludo">hola</i>' | sed -E 's/<i(.*)>(.*)<\/i>/<em\1>\2<\/em>/'
<em id="saludo">hola</em>
$ echo "724342233245" | sed 's/2[0-9]/&&/'
72424342233245

Por otro lado, en sed, tanto la expresión regular como el texto para sustituir puede incluir caracteres no imprimibles, para ello tendremos que usar secuencias de escape, y dos muy usadas son \n (nueva línea, ASCII 10) y \t (tabulación, ASCII 9). Otras secuencias de escape son: \a (ASCII 7), \f (ASCII 12), \r (ASCII 13) y \v (ASCII 11). Cualquier carácter no imprimible e imprimible puede indicarse con las siguientes secuencias de escape:

  • \dnnn - nnn debe ser el código ASCII en decimal del carácter.
  • \onnn - nnn debe ser el código ASCII en octal del carácter.
  • \xnnn - nnn debe ser el código ASCII en hexadecimal del carácter.

Como ejemplo de uso de secuencias de escape, podemos pensar en separar en líneas independientes los número enteros que están en el flujo de entrada, para posteriormente realizar con ellos algún tratamiento especial, sed nos hará la primera parte del trabajo:

$ echo "2394732sldfj2394723asljdf20347327" | sed 's/[[:digit:]]\+/\n&\n/g'

2394732
sldfj
2394723
asljdf
2034732

En el ejemplo anterior se ha usado el modificador g que se explica más abajo en este mismo apartado.

El carácter / se suele utilizar para separar los distintos argumentos del comando s, pero realmente el carácter separador es el primer carácter que vaya a continuación de la s, por ejemplo:

$ echo "724342233245" | sed 's$2[0-9]$&&$'
72424342233245
$ echo "724342233245" | sed 'a$2[0-9]a&&a'
72424342233245
$ echo '<i id="saludo">hola</i>' | sed -E 's$<i(.*)>(.*)</i>$<em\1>\2</em>$'
<em id="saludo">hola</em

En el último ejemplo, al usar el $ como separador de los argumentos, no es necesario proteger el carácter /.

Existen varias secuencias especiales de caracteres que se pueden utilizar en el texto de sustitución para convertir a mayúsculas y/o minúsculas. Estas secuencias son:

  • \u - Convierte a mayúscula el siguiente carácter.
  • \l - Convierte a minúscula el siguiente carácter.
  • \U - Convierte a mayúscula todos los caracteres que le siguen hasta el final del texto de sustitución o hasta que se encuentre un \E o \L.
  • \L - Convierte a minúscula todos los caracteres que le siguen hasta el final del texto de sustitución o hasta que se encuentre un \E o \U.
  • \E - Detiene las conversiones anteriores. Un caso interesante es por ejemplo, \u\1a, si \1 es la cadena nula, la 'a' se convertiría a mayúscula, y si no queremos ese comportamiento, especificaríamos \u\1\Ea. 
$ echo '<i id="saludo">hola</i>' | sed -E 's/<i(.*)>(.*)<\/i>/<em\1>\u\2<\/em>/'
<em id="saludo">Hola</em>
$ echo '<i id="saludo">hola</i>' | sed -E 's/<i(.*)>(.*)<\/i>/<em\1>\U\2\E<\/em>/'
<em id="saludo">HOLA</em>

Modificador g (global)

Por defecto, la sustitución solo se hace sobre la primera coincidencia de la expresión regular dentro de la zona de trabajo, si queremos que se realice sobre todas las coincidencias, añadiremos el modificador g.

$ echo "724342233245" | sed 's/2[0-9]/&&/g'
724243422223324245

Modificador número

Este modificador especifica la número-ésima coincidencia de la expresión regular que se sustituirá.

$ echo "724342233245" | sed 's/2[0-9]/&&/2'
72434222233245

Si se combinan los dos modificadores anteriores, da igual el orden, se sustituirán todas las coincidencias de la expresión regular desde la número-ésima hasta el final. Este comportamiento es específico de la versión GNU de sed.

$ echo "724342233245" | sed 's/2[0-9]/&&/2g'
7243422223324245

Modificador I, i (case-insensitive)

La expresión regular de búsqueda del comando s diferencia entre mayúsculas y minúsculas, con el modificador I o i, este comportamiento se invierte.

$ echo "Un día es un día" | sed 's/u/-/g'
Un día es -n día
$ echo "Un día es un día" | sed 's/u/-/gi'
-n día es -n día

Modificador w nombre-fichero (write)

Con el modificador w nombre-fichero se consigue que si se llega a producir la sustitución, entonces la zona de trabajo se añade al fichero indicado. Al inicio de la ejecución del comando sed, el fichero se crea, y si existiera, se borraría su contenido.

Todo lo que va a la derecha del nombre del modificador se considera el nombre del fichero, por lo que para poner un comando a la derecha se debe hacer en otra opción -e o bien en otra línea del script.

$ sed 's/u/-/w sustituciones' f g
-no
dos
tres
c-atro
$ cat sustituciones
-no
c-atro

Como vemos, este modificador no evita el final de los ciclos, es decir, no impide que la zona de trabajo se envíe a la salida estándar, para ello está la opción -n de sed.

Solo como extensión de GNU, no es estándar, se pueden utilizar los nombres de los ficheros especiales /dev/stdout y /dev/stderr.

Si en un script hay múltiples comandos s con el modificador w que utilizan el mismo fichero, todas añaden información al fichero, en ningún caso, el fichero se sobrescribe.

Modificador p (print)

El modificador p se usa para enviar el contenido de la zona de trabajo a la salida estándar siempre que se haya producido la sustitución.

$ sed -n 's/u/-/p' f g
-no
c-atro