Anda di halaman 1dari 39

Presentación

sed significa stream editor (en español editor de flujo o editor de flujo orientado a líneas). Por su
modo de funcionamiento y concepción, sed es un editor no interactivo.

Al igual que el editor ed (del cual proviene y que lo encontramos aún en las distribuciones
actuales), sed opera sobre una sola línea a la vez, a diferencia de otros editores como vi, emacs,
Nedit, Xedit, etc. que operan sobre una página completa de texto que aparece en pantalla.

El editor ed estaba dotado de un comando que trabajaba sobre el flujo de entrada estándar en vez
que sobre un archivo, y era capaz de mostrar las líneas que contenían una expresión regular. Este
comando cuya sintaxis es g/re/p (global/regular expression/print) dio nacimiento a la utilidad grep.
Luego aparecería una nueva implementación de una versión de ed, que trabajaba únicamente sobre
el flujo de entrada estándar y recibía las instrucciones de un archivo de script. Esta versión fue
bautizada como stream editor, más conocida con el nombre de sed.

El editor de flujo sed lee las líneas de uno o varios ficheros desde la entrada estándar, lee los
comandos desde la entrada estándar, o desde un archivo texto (script), y los agrupa bajo forma de
expresiones (comandos de edición), luego aplica estos comandos y escribe el resultado en la salida
estándar.

Podríamos resumir el mecanismo de funcionamiento de sed de esta manera: lectura de una línea
desde el flujo de entrada (las líneas están delimitada por un carácter de salto de línea), la línea es
procesada en función de los comandos leídos, muestra (o no) del resultado en la salida estándar
(pantalla), continúa con la línea siguiente.

Los comandos aceptan números de líneas, rangos o expresiones regulares (RE o regex) para
seleccionar la o las líneas sobre las que deben operar.

Introducción
sed recibe las instrucciones o comandos desde la línea de comandos o desde un fichero (script) y
aplica cada instrucción, en el orden en que aparece, a cada línea en la entrada estándar. Una vez que
todas las instrucciones han sido aplicadas a la primera línea, la línea es mostrada (o no, dependiendo
de lo que se indique) en la salida estándar (la pantalla o redirigida a un archivo), luego sed procede
a la lectura y el procesamiento de la siguiente línea y así sucesivamente hasta el final del archivo de
entrada (a menos que encuentre una instrucción de salida).

Este mecanismo es llamado ciclo. Se entiende por ciclo a la aplicación de todos los comandos que
componen el script a los datos presentes en el espacio de patrón. Por defecto un ciclo comprende: la
copia de una línea de entrada al espacio de patrón (la línea estando delimitada por el carácter fin de
línea (\n)); normalmente el espacio de patrón está vacío, a menos que un comando "D" haya
terminado el ciclo precedente (en ese caso un nuevo ciclo comenzará con los datos sobrantes en el
espacio de patrón); Sed aplicará los comandos secuencialmente (provenientes de un script o desde
la línea de comandos) a los datos presentes en el espacio de patrón, una vez llegado al final del
script, enviará los datos procesados a la salida estándar, a menos que se indique lo contrario con la
opción -n, y borrará el espacio de patrón. Todos los datos enviados a la salida estándar o a un
fichero, son seguidos por un carácter de fin de línea (\n); copia de una nueva línea o salida si se ha
llegado al final del fichero.

Veamos con la ayuda de un organigrama el funcionamiento de sed mediante un sencillo script que
borra las líneas vacías de un fichero y las líneas que contienen únicamente un carácter almohadilla
(#) al inicio de la línea. Para ello, aquí tenemos un fichero conteniendo algunas líneas vacías,
algunas almohadillas solas, entre ellas una espaciada a la derecha y dos líneas con varias
almohadillas.

El fichero:
#
#
#
##
# Este es un comentario
# Este es otro comentario
#
#
#
###
# Y otro más
#
#
# Y un último comentario
#

El script es relativamente simple. Aquí lo tenemos en una sola línea:


sed -e '/^$/d;/^#$/d'

Y en un script:
#! /bin/sed -f
/^$/d # borrar las líneas vacías
/^#$/d # borrar las líneas conteniendo solo un carácter almohadilla "#"
#+ encontrándose al inicio de la línea y nada detrás

El organigrama:

Graforganigr

Sintaxis
Sintaxis general
sed [-opciones] [comando] [<fichero(s)>]
sed [-n [-e comando] [-f script] [-i[.extension]] [l [corte]] rsu] [<comando>]
[<fichero(s)>]

Sintaxis de un comando
El direccionamiento de una o varias líneas es opcional en todos los comandos
[dirección[,dirección]][!]comando[argumentos]

Poniendo entre llaves un conjunto de comandos, pueden ser aplicados a una línea o rango de líneas.
[dirección[,dirección]]{
comando1
comando2
comando3
}

Estos comandos pueden estar puestos en una sola línea, pero deben ser separados por un punto y
coma ( ;).
[dirección[,dirección]]{comando1; comando2; comando3}

Direccionamiento
Sed puede direccionar directamente una línea (o un rango) por su número de línea o por la
coincidencia con una expresión regular haciendo de patrón.
Un signo de exclamación (!) después de un numero de línea, un patrón o una expresión regular evita
que la línea (o rango) sea procesada.

El direccionamiento se puede efectuar de la siguientes forma:

num

El número de la línea
sed -n 3p fich.txt

inicio~salto

Todas las n líneas (salto) comenzando desde el inicio.


sed -n 1~2p fich.txt

La última línea del último fichero leído en la entrada, o de cada fichero si las opciones -i o -s han
sido especificadas.
sed -n '$ p' fich.txt

sed -ns '$ p' fich*

/exp/

Todas las líneas que coinciden con la expresión regular exp


sed -n '/est/p' fich2.txt

\#exp#

Todas las líneas que coinciden con la expresión regular exp precisando utilizar como delimitador el
carácter # (almohadilla) en lugar del delimitador predeterminado.
sed -n '\#est#p' fich2.txt

num1,num2

Todas las líneas comprendidas entre num1 y num2. Si num2 es inferior a num1, solo num1 es
mostrado.
sed -n '3,6 p' fich.txt

/exp1/,/exp2/

Todas las líneas comprendidas entre exp1 y exp2, comprendidas las líneas conteniendo exp1 y exp2.
Si el intervalo conteniendo las 2 expresiones se repite varias veces, Sed aplicará las instrucciones a
cada intervalo sucesivamente. No obstante si exp2 no es encontrado, las instrucciones son aplicadas
a cada línea comenzando por exp1 hasta el final del fichero.
sed -n '/comentario1/,/comentario2/ p' fich2.txt

num,/exp/
/exp/,num

Todas las líneas comprendidas entre un número de línea y una expresión regular (o a la inversa). En
num,/exp/, no obstante si exp no es encontrado, las instrucciones son aplicadas a cada línea
comenzando por num hasta el final del fichero. En /exp/,num, si num es inferior al numero de línea
correspondiente a exp, solo la línea que contiene exp es mostrada.
sed -n '2,/comentario2/ p' fich2.txt

sed -n '/comentario1/,8 p' fich2.txt

Las opciones (argumentos)


sed acepta opciones (argumentos), pero no demasiadas. Las mas utilizadas son: -n, -e e -i.

-n, --quiet, --silent

Solicitud implícita para evitar mostrar el estado de la memoria principal (buffer). En un script la
notación se hará de esta manera #n (un signo almohadilla seguido del carácter n) y se deberá
encontrar en la primera línea del script.

-e script, --expresión=script

Permite encadenar varios comandos

-f fichero-script, *--file=fichero-script

Lectura de comandos desde el fichero indicado

-i[SUFIJO], --in-place[=SUFIJO]
Edita archivos en el lugar. También da la posibilidad de hacer una copia de respaldo añadiendo la
extensión (-i.BAK)

--posix

Desactiva todas las extensiones de GNU

-r, --regexp-extended

Utiliza expresiones regulares extendidas (ERE):

-s, --separate

Si varios ficheros son ingresados en la entrada, los procesa uno a uno en vez que como uno solo.

-u, --unbuffered

Carga cantidades mínimas de datos desde los ficheros de entrada y libera los almacenamientos
temporales de salida con mayor frecuencia.

--help

Muestra esta ayuda y termina

--version

Muestra información acerca de la versión del programa y termina.

Los comandos
En los capítulos que siguen veremos los comandos utilizados por sed. Mientras que el uso de
algunos de ellos puede parecer sencillo, el uso y la implementación de otros dentro de scripts puede
ser un poco más difícil debido a su sintaxis.

Algunos comandos admiten un rango de direcciones mientras que otros solo admiten una e incluso
ninguna en una minoría de comandos.

Los comandos básicos 1


En este capitulo veremos los comandos más conocidos de Sed cuyo uso es relativamente sencillo.
#
Comentario (no acepta ninguna dirección)

El carácter # (almohadilla) inicia un comentario que se extiende hasta el final de la línea. Se puede
encontrar en la misma línea de un comando.

Si los dos primeros caracteres de un script Sed son #n, la opción -n (no-autoprint) es
forzada. Por lo tanto si tu script debe empezar necesariamente con una línea de comentario
comenzando con la letra n minúscula, utiliza una N mayúscula o inserta un espacio entre la
almohadilla (#) y la n.

q quit
Abandonar (acepta una dirección)

Abandona sed sin ejecutar ningún otro comando ni evaluar otra entrada. La línea actual contenida
en la memoria principal es mostrada a menos que la opción -n haya sido empleada.
sed '3q' fich.txt

d delete
Borrar (acepta un rango de direcciones)

Borra el espacio de patrón y pasa a la siguiente línea de entrada.


sed '3d' fich.txt

p print
Mostrar (acepta un rango de direcciones)

Muestra en pantalla el espacio de patrón actual. No borra el espacio de patrón ni modifica la


ejecución del script. Este comando siempre es empleado conjuntamente con la opción -n, sino la
línea aparecería duplicada. (Utilizar mejor la segunda forma que es mas adaptada ya que el script se
termina en cuanto el patrón o la línea encontrada es mostrada en la salida estándar y no continua
recorriendo el resto del fichero).
sed -n '3p' fich.txt

sed -n '3{p;q}' fich.txt


n next-line
Siguiente línea (acepta un rango de direcciones)

Reemplaza el espacio de patrón actual con la siguiente línea sin comenzar un nuevo ciclo. La línea
reemplazada es enviada a la salida estándar.
echo -e "AAA\nBBB\nCCC\nDDD" | sed -n '/BBB/ {n;p;q}'

{ ... }
Agrupación de comandos (acepta un rango de direcciones)

El empleo de llaves permite agrupar ciertos comandos que serán ejecutados sobre una dirección o
un rango de direcciones. No es necesario protegerlos con un backslash como en el caso del empleo
de expresiones regulares indicando un número de repeticiones.
echo -e "AAA\nBBB\nCCC\nDDD" | sed -n '/BBB/ {n;s/C/Z/2p}'

s substitución
Comando de substitución (acepta un rango de direcciones)

El comando de substitución s es sin ninguna duda el comando mas utilizado del filtro Sed. Su
sintaxis es muy simple:
's/patrón/reemplazo/flag(x)'

Su funcionamiento también es muy simple: si encuentra una cadena que coincide con el patrón o la
expresión regular, la cadena es substituida por la cadena de reemplazo, teniendo en cuenta los
posibles flags.

En los mecanismos de substitución hay que distinguir dos partes: LHS (Left Hand Side = lado
izquierdo) que corresponde a la cadena buscada y RHS (Right Hand Side = lado derecho)
correspondiente a la cadena de reemplazo.

Mientras que la parte izquierda acepta la sintaxis de las BRE (Basic Regular Expression,
expresiones regulares básicas), la parte de la derecha (reemplazo) acepta únicamente tres valores
que pueden ser interpolados: el carácter & (amperstand), las referencias hacia atrás \1 (de 1 al 9),
las opciones \U,\u,\L,\l y \E
Para interpretar literalmente un amperstand (&) o un anti-slash (\) es necesario hacerlas
preceder de un anti-slash:
\& o \\

Flags
Los flags o atributos.

El comando de substitución (s) puede ser seguido de varios flags o atributos. Ciertas combinaciones
no pueden ser hechas como el atributo g (global) y una enésima ocurrencia (N) lo que sería una total
incoherencia. Siguiendo la misma lógica, el atributo w debe ser el último de la lista.

g: global

Efectúa el reemplazo de todas las ocurrencias encontradas correspondientes al patrón o a expresión


regular.
echo "AAAAA" | sed 's/A/B/'
BAAAA
echo "AAAAA" | sed 's/A/B/g'
BBBBB

N enésima ocurrencia

Reemplaza únicamente la enésima ocurrencia encontrada correspondiente al patrón o expresión


regular.
echo "AAAAA" | sed 's/A/B/3'
AABAA

p print (visualización)

Si se ha producido una substitución, entonces muestra el espacio de patrón actual. Necesita la


presencia de la opción -n.
$ var="línea1\nlínea2\nlínea3\nlínea4\nlínea5"
$ echo -e "$var"
línea1
línea2
línea3
línea4
línea5
$ echo -e "$var" | sed '3 s/e3/e n° 3/'
línea1
línea2
línea n° 3
línea4
línea5
$ echo -e "$var" | sed -n '3 s/e3/e n° 3/'
$ echo -e "$var" | sed '3 s/e3/e n° 3/p'
línea1
línea2
línea n° 3
línea n° 3
línea4
línea5
$ echo -e "$var" | sed -n '3 s/e3/e n° 3/p'
línea n° 3

w fichero - Write (escritura en un fichero)

Si se ha producido una substitución, entonces escribe el espacio patrón en el fichero especificado.


Solo es aceptado un espacio entre el atributo w y el nombre del fichero.
$ var="línea1\nlínea2\nlínea3\nlínea4\nlínea5"
$ echo -e "$var" | sed -n '3 s/e3/e n° 3/pw fich.out'

e evaluate (evaluación)

Permite ejecutar un comando mediante el shell y substituir el resultado con el del patrón,
únicamente si se ha encontrado una ocurrencia.

Ejemplo 1:
$ echo $var
línea1\nlínea2\nlínea3\nlínea4\nlínea5\nlínea6\nlínea7\nlínea8\nlínea9
$ echo $A
Bonjour
$ echo -e "$var" | sed 's/.*5/echo '$A'/e'
línea1
línea2
línea3
línea4
Bonjour
línea6
línea7
línea8
línea9
$
Ejemplo 2:
$ cat plop
0x00000000 0 root 777
0x00000000 65537 user1 600
0x00000000 98306 user1 600

$ echo -e "$var" | sed 's/.*5/cat plop/e'


línea1
línea2
línea3
línea4
0x00000000 0 root 777
0x00000000 65537 user1 600
0x00000000 98306 user1 600
línea6
línea7
línea8
línea9
$

I Ignorar diferencia entre mayúsculas y minúsculas

Permite ignorar la diferencia entre mayúsculas y minúsculas en la búsqueda de una coincidencia


con el patrón.
$ echo "BonJouR" | sed 's/bONjOUr/Salut/'
BonJouR

$ echo "BonJouR" | sed 's/bONjOUr/Salut/I'


Salut

El modificador M para la búsqueda de coincidencias con expresiones regulares es una nueva


extensión de GNU Sed que permite que coincidan el carácter ^ y el carácter $ con una cadena vacía
después de una nueva línea y una cadena vacía antes de una nueva línea respectivamente. Ya
existían los caracteres especiales \` y ' (en modo basico o extendido de expresiones regulares) que
hacían coincidir el inicio y el fin del buffer. M siendo multilínea.

Para explicarlo más claramente, el espacio de patrón contiene una línea leída desde la entrada y
pueden ser agregadas otras líneas utilizando comandos como N,G, x, etc. Todas estas líneas en el
espacio de patrón son separadas por el carácter de fin de línea \n pero son vistas por sed como una
sola línea cuyo inicio empieza antes de la primera línea y termina al final de la ultima línea. Con el
flag M cada carácter representando el inicio (^) y el final ($) de línea retoma su sentido inicial y
hace coincidir el inicio y el final de la línea con cada línea que se encuentra en el espacio de patrón.

A continuación un ejemplo que muestra el empleo del flag M:

Primer caso:
$ echo -e "foo\nbar" | sed 'N;s/^.*$//'
$

En este caso, ^ y $ apuntan al inicio y al final del buffer que después de la aplicación del comando
N contiene foo\nbar$, y la expresión regular coincide con todo lo que se encuentra entre los dos
caracteres que indican el inicio (^) y el final ($) sin tener en cuenta el carácter que representa el
final de la línea \n.

Segundo caso:
$ echo -e "foo\nbar" | sed 'N;s/^.*$//M'
bar
$

En este caso, ^y $ apuntan al inicio y el final de la primera línea en el buffer, que como en el caso
anterior después de la aplicación del comando N contiene foo\nbar$, pero con la diferencia que la
expresión regular coincide únicamente con los caracteres que se encuentran antes del carácter fin de
línea \n.

Tercer caso:
$ echo -e "foo\nbar\nfoobar\nbarfoo" | sed -e ':boucle; N; $! b boucle;
s/^.*$//M3'
foo
bar

barfoo
$

En este tercer caso, el buffer después de la ejecución del comando N (dentro de un bucle que tiene
por efecto cargar la totalidad de las líneas en el buffer), se parece a foo\nbar\nfoobar\nbarfoo$ y la
substitución se aplica únicamente a la tercera línea materializada por el carácter \n.

A continuación otros 2 ejemplos:

El primero:
$ echo -e "foo\nfoo\nfoo\nbar\nfoo" | sed 'N;/bar$/s/^/>/Mg;P;D'
foo
foo
>foo
>bar
foo
$

Aquí son cargadas 2 líneas al espacio de patrón, si el final del buffer no termina en bar, entonces la
primera línea del buffer es mostrada (P), luego borrada (D), y se retoma la ejecución del script con
la carga de la línea siguiente donde se comprueba nuevamente la coincidencia con la expresión
regular. Si se encuentra una ocurrencia, se agrega un (>) al inicio de la línea, luego la primera línea
del buffer es mostrada (P), luego borrada (D) y se retoma la ejecución del script...

El segundo:
$ echo -e "foo\nfoo" | sed 'N;s/^/>/;s/\n/\n>/g'
>foo
>foo

$ echo -e "foo\nfoo" | sed 'N;s/^/>/Mg'


>foo
>foo
$

En este ejemplo se muestra la utilidad del flag M utilizando únicamente una expresión para agregar
un (>) al inicio de cada línea contenida en el espacio de patrón después de llamar al comando N.

Los comandos básicos 2


y
Transposición de caracteres (acepta un rango de direcciones)

El comando y permite convertir cualquier carácter enumerado en la cadena carácter-origen por su


homólogo, en su lugar, que se encuentra en la cadena carácter-destino.

El empleo más común de este comando es sin dudas el reemplazo de caracteres acentuados. Veamos
un ejemplo:
sed '
y/àâéèêëîïôöùûü/aaeeeeiioouuu/
y/ÀÂÉÈÊËÎÏÔÖÙÛÜ/AAEEEEIIOOUUU/
' fichero.txt

a\
text
Agregar (acepta una dirección)
Agrega el texto text después de la línea que coincide con el número de línea, patrón o expresión
regular, y antes de la lectura de la línea siguiente. text corresponde a una sola línea de texto, que sin
embargo puede contener saltos de línea precedidos de \ (backslash).
sed '/Línea n° 5/ a\
Bonjour
' fich.txt

i\
text
Inserción (acepta una dirección)

Inserta el texto text antes de la línea que coincide con el número de línea, patrón o expresión
regular. text corresponde a una sola línea de texto, que sin embargo puede contener saltos de líneas
precedidos de \ (backslash).
sed '/Línea n° 4/ i\
Bonjour
' fich.txt

c\
text
Intercambio (acepta un rango de direcciones)

Cambia la línea que coincide con el número de línea, patrón o expresión regular con text. text
corresponde a una sola línea de texto, que sin embargo puede contener saltos de líneas precedidos
de \ (backslash).
sed '/Línea n° 2/,/Línea n° 6/ c\
Anulado\
A causa\
de trabajos
' fich.txt

r fichero read
Lectura (acepta una dirección)

Lee el contenido de fichero en el espacio de patrón luego de la dirección especificada. Únicamente


debe haber un espacio entre el comando y el nombre del fichero. Lo que sigue después del espacio,
hasta el final de la línea, es considerado el nombre del fichero. De aquí que cualquier espacio
(incluido la tabulación) será considerado como parte del nombre. Si el fichero no existe, ningún
mensaje de advertencia aparecerá en la salida estándar ni en otro lugar. Si el fichero no se encuentra
en el mismo directorio en el que es ejecutado el comando, se debe especificar la ruta completa del
fichero.

Por ejemplo lo podemos utilizar para agregar una firma al final de una serie de ficheros. Para
ilustrar esto, vamos a agregar el contenido del fichero firma.txt al final de todos los ficheros
correspondientes al patrón fich*.txt) (observa bien el siguiente ejemplo y observa el empleo del
switch -s):
sed -s '$ r firma.txt' fich*.txt

w fichero write
Escribir (acepta una sola dirección).

Escribe la línea que esta siendo procesando en el fichero indicado luego del comando w. Al igual
que el comando r (lectura), únicamente debe haber un espacio entre el comando y el nombre del
fichero. Todo lo que esta después de este espacio, hasta el final de la línea, es considerado como el
nombre del fichero. De aquí que cualquier espacio (incluida una tabulación) será considerado como
parte del nombre. Si un fichero con el mismo nombre ya existe, será aplastado sin ninguna
advertencia ni confirmación en cada invocación del script. En cambio, si varias instrucciones del
comando w deben ser escritas en un mismo fichero desde un script, cada escritura es agregada al
final del fichero.

Si el fichero no existe será creado, incluso si el proceso es nulo en la salida (ninguna escritura
enviada). A continuación un pequeño escenario para poner este comando en aplicación. Desde un
fichero direcciones.txt agrupando nombres de servicios postales asociados a un código postal y su
ciudad de referencia, extraer el nombre del servicio postal y la ciudad asociada y enviarla a un
nuevo fichero que lleva el nombre del departamento. Este script llamado foo.sed será invocado de
la manera siguiente:
sed -f foo.sed < direccións.txt

Contenido del fichero foo.sed:


#n
/\b31/{
s/[0-9][0-9]*//
w Haute-Garonne
}
/\b34/{
s/[0-9][0-9]*//
w Hérault
}
/\b66/{
s/[0-9][0-9]*//
w Pyrénées-Orientales
}
=

Muestra el número de la línea actual.


sed -n '/patrón/=' fichero

l [N] --line-length=N
Corte (acepta un rango de direcciones)

Muestra caracteres no imprimibles - N permite especificar la longitud de corte de línea deseada.


sed -n l fichero # Muestra caracteres no imprimibles
sed -n 'l 8' fichero # lo mismo pero con un retorno a la línea cada 8
caracteres

Los comandos avanzados


Además de los comandos que acabamos de ver, Sed posee otros comandos, poco utilizados y para
algunos no muy fácil de utilizar, pero que permiten realizar ciertas tareas.
Los comandos precedentes utilizan principalmente el siguiente mecanismo:
Lectura de una línea del fichero de entrada en el espacio de patrón a la cual se le aplica cada uno de
los comandos del script. Cuando se alcanza el final del script, la línea es enviada a la salida
estándar, el espacio patrón es borrado, una nueva línea es leída desde la entrada y el control es
pasado nuevamente al inicio del script.

Con los comandos que siguen, veremos cómo podemos intervenir en el desarrollo del script:
modificar el flujo de entrada bajo ciertas condiciones, almacenar partes de líneas, probar
condiciones, etc.

Estos comandos pueden ser clasificados en 3 grupos: los comandos multilíneas (N,D,P), los
comandos que utilizan la memoria secundaria (h,H,g,G,x), los comandos de test que utilizan
etiquetas (:,b,t,T)

Los comandos multilíneas


N Next
Siguiente (acepta un rango de direcciones)

El comando N posiciona el carácter nueva línea (\n) al final del contenido del espacio patrón y
agrega la línea siguiente del flujo de entrada en el espacio patrón. Si el final del fichero de entrada
es alcanzado, sed termina la ejecución sin proceder a la ejecución de un nuevo comando. El carácter
nueva línea incorporado en el espacio patrón puede ser asociado a la secuencia de escape \n. en un
espacio patrón multilíneas, los meta-caracteres ^ y $ concuerdan con el inicio y final del espacio
patrón y no los inicios y finales de las líneas precedentes o siguientes al carácter nueva línea
incorporada.

El ejemplo que sigue busca una línea que contiene el patrón C. Si este es encontrado, agrega la
siguiente línea al espacio patrón y substituye el carácter final de línea \n por un guión rodeado de un
espacio en ambos lados:
echo -e "A\nB\nC\nD\nE" | sed '/C/{N;s/\n/ - /}'

D Delete
Borrar (acepta un rango de direcciones)

El comando D borra el contenido del espacio patron hasta el primer carácter delimitando una nueva
línea (\n). si aun quedan datos en el espacio patron, un nuevo ciclo es iniciado con este contenido
(sin leer una nueva línea desde la entrada), si no un nuevo ciclo es iniciado con la línea siguiente.

Para mostrar el uso del comando D, tomaré un ejemplo dado en el excelente libro publicado por
O'Reilly (sed & awk, Second Edition) y que resume muy bien el mecanismo de este comando
similar al comando d.

El fichero de referencia (comando_D.txt):


Esta línea es seguida de una línea vacía.
Esta línea es seguida de 2 líneas vacías.
Esta línea es seguida de 3 líneas vacías.
Esta línea es seguida de 4 líneas vacías.
Fin del archivo

Por razones de presentación inherentes a esta sección, en el fichero solo hay 3 líneas vacías
debajo de la línea Esta línea es seguida de 4 líneas vacías". Deberás agregar una cuarta
línea si deseas comprobar este ejemplo.

Ya que el objetivo es agrupar las líneas vacías consecutivas en una sola. El comando d parece ser el
apropiado para esta tarea. Veamos un primer script utilizando este comando:
sed '
/^$/{
N
/^\n$/d
}' comando_D.txt

Para ello utilizaremos un patrón que nos permita coincidir con una línea vacía /^$/. En cuanto una
línea vacía sea encontrada pediremos que sea cargada la línea siguiente al espacio de patrón con el
comando N. Una vez esta línea cargada, comprobaremos que el patrón presente en el espacio de
patrón coincida con el patrón /^\n$/, y si es así, lo borramos (comando d). Pero esta sintaxis
funciona únicamente cuando el número de líneas es impar. Esto se explica por el hecho de que el
comando d borra la totalidad del contenido del espacio de patrón.
Efectivamente, cuando una línea vacía es encontrada la línea siguiente es cargada (N), si esta línea
es vacía, el espacio patrón es borrado (d) y comienza un nuevo ciclo con una nueva línea. Así, si
esta nueva línea (3ra) es vacía, y la siguiente no, entonces el comando de borrado (d) no se aplica y
se muestra la línea vacía.

En cambio si reemplazamos el comando d por D:


sed '
/^$/{
N
/^\n$/D
}' comando_D.txt

Obtenemos el resultado esperado. En efecto, el comando D borra únicamente la parte del espacio
patrón comprendido antes del primer carácter /n (salto de línea), de aquí si 2 líneas vacías se
encuentran en el espacio patrón, solo la primera línea es borrada y el script reinicia con el contenido
del espacio patrón (una línea vacía), entonces una nueva línea es cargada, si no es vacía, las 2 líneas
contenidas en el espacio patrón son enviadas a la salida estándar, si no la primera parte es borrada y
el escenario se repite...

En otras palabras, si dos líneas vacías se encuentran en el espacio patrón, solo la primera línea es
borrada, si es una línea vacía seguida de texto, son enviadas a la salida estándar.

P Print
Visualización (acepta un rango de direcciones).

Al igual que su similar en minúscula que muestra el contenido del espacio patrón, el comando P
muestra el contenido del espacio patrón hasta el primer carácter delimitando una nueva línea (\n).
Cuando el ultimo comando del script es alcanzado, el contenido del espacio patrón es mostrado
automáticamente en la salida estándar (a menos que la opcion -n o #n haya sido empleada).

Los buffers
El editor de flujo Sed dispone de dos buffers que permiten almacenar la o las líneas que se están
procesando.

Estas memorias son generalmente denominadas pattern space para la memoria principal, que la
podemos traducir por espacio patrón, y hold space para la memoria secundaria.

El espacio de patrón (pattern space) es el espacio de memoria en el que son mantenidos los datos
(la o las líneas) seleccionados mientras sean procesados.
El hold space es el espacio de memoria en el que los datos (la o las líneas) son almacenados
temporalmente.

Existen 5 comandos que permiten pasar de un espacio a otro, a continuación un breve resumen:

h Copia el contenido del espacio patrón en el hold space.

H Agrega el contenido del espacio patrón en el hold space.

g Copia el contenido del hold space en el espacio patrón.

G Agrega el contenido del hold space en el espacio patrón.

x Intercambia el contenido de las 2 memorias

Salvo el comando x, los otros comandos funcionan en parejas y actuan para cada binomio a la
manera de redirecciones (>, >>, <,<<) interpretes de comandos en el shell y en el bash o ksh. Su rol
se podria traducir de este modo:

h > Aplasta el contenido.

H >> Agrega contenido.

g < Aplasta el contenido.

G > Agrega contenido.

A continuación una breve definición de cada comando que puede afectar el espacio patrón:

h hold pattern space


(acepta un rango de direcciones)

El comando h copia el contenido del espacio patrón en la memoria secundaria, destruyendo el


contenido existente.

H Hold pattern space (acepta un rango de direcciones)

El comando H agrega el contenido de espacio patrón al contenido de la memoria secundaria. El


antiguo contenido y el nuevo son separados por una nueva línea representada por el carácter \n. Una
nueva línea (\n) es agregada al espacio patrón, incluso si éste esté vacío.

g get contents
Copia el contenido (acepta un rango de direcciones)

El comando g copia el contenido de la memoria secundaria en el espacio patrón, destruyendo el


contenido existente.

G Get contents
Agrega contenido (acepta un rango de direcciones)

El comando G agrega el contenido de la memoria secundaria al espacio patrón. El contenido que


existia y el nuevo son separados por una nueva línea representada por el carácter \n.

x eXchange
Intercambio (acepta un rango de direcciones)

El comando x intercambia el contenido de las dos memorias (principal y secundaria). La memoria


secundaria inicia su ciclo con una línea vacía. Si aplicamos el comando x a la primera línea de un
fichero, está línea es colocada en la memoria secundaria y será reemplazada por el contenido de esta
memoria secundaria, es decir una línea vacía. También debemos saber, que según este principio, la
última línea de un fichero es colocada en la memoria secundaria pero nunca es restituida en el
espacio patrón y de aquí que no será nunca mostrada a menos que se haga una solicitud implícita.

Al final de este documento encontraras algunos ejemplos comentados acerca del uso de la memoria
principal y secundaria de Sed, y para comenzar veremos un pequeño ejemplo (sacado de la obra de
las ediciones O'Reilly), muy fácil de comprender, pero que nos advierte acerca de unos de los
errores a veces incomprensibles que puede ocurrir.

Uno de estos errores tiene que ver con la memoria secundaria. Cuando enviamos el contenido del
espacio patrón, y luego procedemos a diversas operaciones, y estas operaciones restituyen el
contenido de la memoria secundaria únicamente bajo ciertas condiciones, puede ocurrir que este
contenido no sea nunca restituido en el espacio patrón y de aquí, jamás será enviado a la salida
estándar...

Veamos la demostración. Vamos a mostrar la siguiente variable:


$ A="1\n2\n11\n22\n111\n222"
$ echo -e "$A"
1
2
11
22
111
222

Y pedir a Sed que invierta las líneas comenzando por 1 con las comenzando por 2.

Para ello comenzaremos por emparejar las líneas comenzando por 1, copiar el contenido en la
memoria secundaria con el comando h, luego vaciar el espacio patrón, utilizando el comando d. el
control es enviado al inicio del script, donde una nueva línea es cargada (con un 2), la primera
comparación (/1/) fracasa, pero la segunda (/2/) es verdadera, por lo que el contenido de la memoria
secundaria es agregado al espacio patrón, que contiene 2\n1$. Como hemos llegado al final del
script, el contenido del espacio patrón es mostrado y reemplazado por la siguiente entrada (11) y el
script vuelve a comenzar, y así sucesivamente...

Este es el script:
echo -e "$A" | sed '
/1/{ # si el patrón está presente
h # copiarlo en la memoria secundaria
d # borrar el contenido de la memoria principal
}
/2/{ # si el patrón está presente
G # agregar el contenido de la memoria secundaria
}'

La visualización final:
2
1
22
11
222
111

Como lo hemos visto, todo marcha bien. Pero que pasaría si pusiéramos un 333 en lugar de 22. Esto
es justamente lo que vamos a ver.
En primer lugar, la visualización de la nueva variable:
$ A="1\n2\n11\n33\n111\n222"
$ echo -e "$A"
1
2
11
33
111
222

Y el filtrado hecho por sed :


$ echo -e "$A" | sed '/1/{h;d};/2/{G}'
2
1
33
222
111

Y bien como podemos ver, la visualización del 11 quedo atrás. Y ¿por qué? Como lo hemos dicho al
inicio de este ejemplo, simplemente porque el contenido de la memoria secundaria es restituida
únicamente en el espacio patrón si y solamente si un patrón conteniendo un 2 es encontrado. En
caso contrario, el script continúa su camino, dicho de otro modo, muestra la línea presente en el
espacio patrón (33) y pasa el control al inicio del script que carga la línea siguiente (111), línea que
satisface la condición del 1er motivo (/1/) y envía su contenido al espacio secundario, destruyendo
los datos presentes (11).

Por lo tanto, hay que tener cuidado durante la elaboración de ciertos scripts en restituir el contenido
de la memoria secundaria.

Etiquetas
Las etiquetas (label) permiten saltar a una ubicación precisa dentro del script. Sed posee tres
comandos especialmente para esto. Un comando incondicional b y dos comandos condicionales t et
T de [tT]est.

La sintaxis para designar una etiqueta se limita a colocar al inicio de línea (por un script) dos puntos
seguidos de una letra (o cadena de letras a fin de formar una palabra, ésta ultima es recomendado
para una mejor lectura del código).
:etiqueta

Esta etiqueta será llamada en el script utilizando los comandos "b, t o T. Simplemente
anteponiendo su nombre con el comando deseado.
b etiqueta
t etiqueta
T etiqueta

Emplame condicional
b branch
(acepta rango de direcciones)

El comando b permite transferir incondicionalmente la ejecución del script a la posición indicada


por la etiqueta pasada como argumento. Si no es pasado ningún argumento, el comando envía al
final del script. El comando que se esta ejecutando es mostrado a menos que la opción -n estaba
activa y el script retoma su ejecución con la próxima línea del flujo de entrada.

Empalme condicional
t test (acepta rango de direcciones)

El comando t permite transferir condicionalmente la ejecución del script a la posición indicada por
la etiqueta pasada como argumento si un comando de substitución ha tenido éxito en la línea que se
esta procesando o en el ultimo empalme condicional. Si ningún argumento es pasado, el comando
envía al final del script.

T test (acepta rango de direcciones)

El comando T permite transferir condicionalmente la ejecución del script a la posición indicada por
la etiqueta pasada como argumento si un comando de substitución ha fracasado en la línea que se
está procesando o en el ultimo empalme condicional si ningún argumento es pasado, el comando
envía al final del script.

SED: The Stream EDitor - Part II

Este artículo es una introducción al uso del editor de flujo SED. El articulo intenta cubrir
ciertas funcionalidades poco conocidas, por no decir casi desconocidas, que hacen de SED
una herramienta indispensable en la caja de herramientas de todo usuario de Linux que desea
dominar el procesamiento de ficheros vía una consola y un shell.

Object 1

• Los delimitadores
• Delimitadores de comandos
• Delimitador de patrón
• El metacaracter '&'
• Las subexpresiones y las referencias hacia atrás
• Las subexpresiones
• Las referencias hacia atrás
• Expresión regular precedente
• La negación
• La agrupación de comandos
• El reemplazo de variables
• Las expresiones regulares
• Los caracteres de escape
• Otros
• Las clases de caracteres
• Las diferentes versiones
• Unix
• Windows
• Depuradores
• Cuando no debo utilizar Sed
• Limites conocidos de las diferentes versiones
• Referencias
• Libros
• Enlaces
• Principiantes y conocedores
• Avanzados
• IRC
• Consulta también: Sed sustituir caracteres especiales

Los delimitadores
Delimitadores de comandos
De manera predeterminada, Sed utiliza como delimitador para su mecanismo de substitución la
barra oblicua / (slash):

Object 2

sed 's/patrón/reemplazo/' fichero

Para la mayoría de casos, esta opción por defecto resulta suficiente, pero puede resultar un
problema si el patrón o la cadena de reemplazo también contienen uno o más slashes como en el
caso de la ruta de un archivo.
Evidentemente puedes proteger los slashes anteponiéndoles un / (anti-slash o barra oblícua
invertida), pero esto resulta una operación muy fastidiosa si el patrón (o la cadena de reemplazo)
contiene varios, volviendo la lectura del código bastante difícil:
sed 's/\/home\/jp\/Docs\/CCM\/SED/\/mnt\/servidor\/docs/' fichero
Hasta puede ser imposible si el patrón (o la cadena de reemplazo) es una variable que debe ser
interpretada:
var="/home/jp/Documentos/CCM/SED/"
sed 's/'$var'/\/mnt\/servidor\/docs/' fichero

o (expresión entre doble apóstrofes)


sed "s/$var/\/mnt\/servidor\/docs/" fichero

Felizmente, Sed permite reemplazar el delimitador por defecto con el carácter de nuestra elección
(#,|,!,§,etc.), siempre y cuando no forme parte del patrón (o la cadena de reemplazo):
sed 's#/home/jp/Docs/CCM/SED#/mnt/servidor/docs#' fichero

Este carácter puede ser cualquier letra siempre y cuando no esté contenida en el patrón (o la cadena
de reemplazo):
echo "hola" | sed 'sZbZBZ'

Si utilizas el carácter ! (signo de exclamación) como separador, debes encerrar la expresión


con apostrofes simples para que el shell no interprete el carácter ! (empleado normalmente
para gestionar el historial de los comandos).

Delimitador de patrón
Como lo hemos visto, Sed utiliza un patrón, encerrado entre / (slash), para buscar coincidencias en
las líneas de un fichero. El slash utilizado por defecto, puede ser cambiado por cualquier otro
carácter, simplemente anteponiendo a la primera ocurrencia de este carácter un \ (backslash).
Tomemos el ejemplo de una ruta como criterio de búsqueda. Bajo está forma, vemos que la lectura
del código no es fácil:
sed -n '/\/home\/jp\/Docs\/CCM\/SED/p' fichero

Sin embargo, si utilizamos el carácter almohadilla # como delimitador, tendremos:


sed -n '\#/home/jp/Docs/CCM/SED#p' fichero
El metacaracter '&'
A menudo, el mecanismo de substitución se limita a buscar un patrón a fin de substituirlo por si
mismo y agregándole algo, por ejemplo, buscar la cadena Sed the Stream EDitor en un fichero y
agregarle Sed the Stream EDitor (Editor de flujo).
Podríamos escribir:
sed 's/Sed the Stream EDitor/Sed the Stream EDitor (Editor de flujo)/g' fichero

El metacaracter & (Ampersand) nos permite reemplazar todas las cadenas de caracteres que
coinciden con el patrón (o la expresión regular) ingresado como 1er argumento.

Aquí la noción de primer argumento no es muy explicita, pero se vera su importancia con
las expresiones regulares y en el capitulo de las sub-expresiones.
Por lo tanto nuestro comando se escribirá de esta manera:
sed 's/Sed the Stream EDitor/& (Editor de flujo)/g' fichero

Supongamos que tenemos que buscar todas las cadenas numéricas (1 o varias cifras consecutivas)
en un fichero y deseamos anteponer a cada una de estas cadenas n° (observa el espacio después de
el °). El comando seria:
sed 's/[0-9][0-9]*/n° &/g' fichero

Necesariamente se debe utilizar la expresión \& para obtener un & literal en una cadena de
reemplazo, si no se generarán errores.

Las subexpresiones y las referencias hacia atrás


Las subexpresiones
\(...\)

Una subexpresión es una parte de una expresión regular, encerrada entre paréntesis, que
posteriormente podemos utilizar en la substitución. Los paréntesis deben ser protegidos con
backslashes, a menos que la opción -r haya sido empleada.

Las referencias hacia atrás


\1 \2 \5

Para referirnos a cada subexpresión en la cadena de reemplazo, utilizamos un número que


corresponde a la posición que ocupa en la expresión regular. Este número debe estar protegido por
un backslash. Únicamente podemos referirnos a 9 subexpresiones numeradas del \1 al \9. Estas
referencias también son llamadas referencias hacia atrás.

A continuación algunos ejemplo con nombre de ciudades francesas y su código postal


correspondiente:

Archivo de referencia:
$ cat plop
31000 Toulouse
34000 Montpellier
66000 Perpignan

En este ejemplo, la subexpresión \([0-9]*\) coincidirá con cualquier cadena numérica y es


referenciada por la referencia hacia atrás \1:
$ sed 's/\([0-9]*\).*/\1/' plop
31000
34000
66000

Esta vez, buscamos las coincidencias de 2 subexpresiones, una numérica y la otra conteniendo el
resto de la línea, pero sin incluir el carácter de tabulación que separa el código postal del nombre de
la ciudad. Luego utilizamos la referencia hacia atrás \1 (código postal) y \2 (nombre de la ciudad)
para mostrar el resultado bajo la forma: nombre de la ciudad > código postal.
$ sed 's/\([0-9]*\)\t\(.*\)/\2 > \1/' plop
Toulouse > 31000
Montpellier > 34000
Perpignan > 66000
En este tercer y último ejemplo, buscamos las coincidencias de una subexpresión con cada parte de
la línea, es decir el código postal (\1), la tabulación (\2) y el nombre de la ciudad (\3)
$ sed 's/\([0-9]*\)\(\t\)\(.*\)/\3\2\1/' plop
Toulouse 31000
Montpellier 34000
Perpignan 66000

Una referencia hacia atrás puede llamar a una subexpresián las veces que se desee en la cadena de
reemplazo. Retomando el último ejemplo, veamos la demostración con la repetición de la
tabulación en diversos lugares:
$ sed 's/\([0-9]*\)\(\t\)\(.*\)/\2\3\2\2\1/' plop
Toulouse 31000
Montpellier 34000
Perpignan 66000

Expresión regular precedente


Cuando encuentra una coincidencia entre una cadena y una expresión regular, Sed pone en su buffer
dicha cadena por lo que es posible referirse a esta cadena en la 1ra parte del comando de
substitución s (LHS) sin mencionarla literalmente. En otras palabras, un comando del tipo
's//cadena_de_reemplazo/' substituirá la ultima expresión regular encontrada por Sed con la
cadena_de_reemplazo.

Para ilustrar esto, retomemos nuestro fichero con las ciudades y los códigos postales. Vamos a
buscar las líneas que contengan el patrón Montpellier, las otras serán borradas (d) y substituiremos
Montpellier por Béziers:
$ cat plop
31000 Toulouse
34000 Montpellier
64000 Perpignan
$ sed '/Montpellier/!d; s//Béziers/' plop
34000 Béziers

Para tratar lo relacionado a las subexpresiones, referencias hacia atrás y expresión regular
precedente, el ejemplo precedente muestra otra faceta de las posibilidades que ofrece sed. Si el
patrón buscado es encerrado entre paréntesis, entonces se convierte en una subexpresión que luego
puede ser invocada en la parte derecha del comando s:
sed '/\(Montpellier\)/!d;s//Béziers-\1/' plop
34000 Béziers-Montpellier
$ sed '/\(Mon\)tpellier/!d;s//Béziers-\1blanc/' plop
34000 Béziers-Monblanc
La negación
A veces puede ser útil excluir una línea que coincide con un patrón (o un rango de lineas) para que
no sea procesada. Para ello, Sed utiliza el carácter ! (signo de exclamación) que como en la mayoría
de herramientas derivadas de Unix expresa la negación, exactamente como lo hace el comando grep
-v.

Para ello, tan solo hay que poner a continuación del patrón (o el numero de línea o rango de lineas)
el carácter !:
sed -n '3 !p' fich.txt
sed -n '3,8 !p' fich.txt
sed -n '/indice/! p' fich3.txt

A menudo encontramos en los scripts Sed, la expresión $! que significa mientras no se alcance la
ultima línea y permite efectuar uno o varios comandos mientras esta condición sea verdadera.

Podemos comparar diferentes maneras de escribir la sintaxis de un comando, pero obteniendo un


mismo resultado.
echo -e 'a\nb\n\nc\nd\ne\n\nf\ng' | sed '/./! d'
echo -e 'a\nb\n\nc\nd\ne\n\nf\ng' | sed '/^$/ d'
echo -e 'a\nb\n\nc\nd\ne\n\nf\ng' | sed -n '/^$/! p'
echo -e 'a\nb\n\nc\nd\ne\n\nf\ng' | sed -n '/./ p'

La agrupación de comandos
/dirección/{...}
(acepta un rango de direcciones)

Las llaves permiten agrupar comandos que serán ejecutados en una dirección o en un rango de
direcciones. Dentro de la agrupación de estos comandos podemos encontrar otras direcciones así
como otros comandos agrupados también entre llaves.

Su principal función, indicar una línea (o rango de líneas) y aplicar sucesivamente uno o varios
comandos. El procesamiento es realizado sobre el contenido del buffer y no sobre la línea original,
por lo que las modificaciones realizadas pueden condicionar los criterios de selección posteriores.
sed '
/a/{ # solo la línea que contiene "a"
s/a/c/g # reemplazar todas las "a" por "c"
/c/{ # solo la línea que contiene "c" de la línea que coincide
s/c/A/g # reemplazar todas las "c" por "A"
}
}
' < <(echo -e "aaa\nbbb\nccc\nddd")
AAA
bbb
ccc
ddd

$ echo -e "aaa\nbbb\nccc\nddd" | sed '/a/{s/a/c/g;/c/{s/c/A/g}}'


AAA
bbb
ccc
ddd

En un grupo de comandos (en un script), cada comando debe iniciar sobre su propia línea, las llaves
y el conjunto de comandos deben estar en líneas separadas. La llave que abre debe encontrarse al
final de la línea, mientras que la llave que cierra debe necesariamente encontrarse sola en una línea.
Atención, no debe haber ningún espacio después de las llaves.

El reemplazo de variables
Puede darse el caso que dentro de un script Sed necesitemos pasar una variable como argumento, ya
sea como patrón o en una u otra de las partes (LHS o RHS) durante una substitución. Como lo
mencione anteriormente, habrá que prestar atención a los caracteres presentes en la variable a fin de
adaptar los apóstrofes a utilizar.

En efecto, por defecto Sed utiliza apóstrofes simples para encerrar las expresiones, pero este
mecanismo en shell bloquea justamente la expansión de las variables; por lo que el empleo de
apóstrofes simples impedirá una buena interpretación de la variable.
var=A; echo 'azerty' | sed 's/a/$var/'
$varzerty

Inicialmente, es posible reemplazar estos apóstrofes simples por apóstrofes dobles, lo que en la
mayoría de casos será suficiente para permitir la interpretación correcta de la variable.
var=A; echo 'azerty' | sed "s/a/$var/"
Azerty

Sin embargo puede ser más conveniente utilizar esta sintaxis:


var=A; echo 'azerty' | sed 's/a/'"$var"'/'
Azerty

En este caso, no es muy fácil comprender por qué es preferible utilizar una mezcla de apóstrofes
simples y dobles. En realidad, la palabra "mezcla" no es el término mas apropiado, es más
apropiado emplear la palabra "excluir", ya que con esta sintaxis, excluimos la variable de la
expresión, lo que permite que sea interpretada por el shell, pero protege dentro de la expresión la
interpretación de posibles caracteres propios al shell. Para comprender mejor esto, veamos un
ejemplo:
La visualización por el shell de 6 letras del alfabeto, cada una en una línea, en la que la letra A es
repetida dos veces. Después de haber asignado esta letra (A) a una variable ($var), vamos a pedir a
Sed que no muestre las líneas conteniendo esta variable, empleando la sintaxis incluyendo la
negación, es decir el signo de exclamación (!).
Primero, escribamos la expresión con apóstrofes simples:
var=A; echo -e "A\nB\nC\nA\nD\nE" | sed -n '/$var/!p'
A
B
C
A
D
E

Observamos que todas las letras son mostradas y es normal ya que la variable no ha sido
interpretada por el shell debido a los apóstrofes simples.

Ahora, pongamos la expresión entre apóstrofes dobles:


var=A; echo -e "A\nB\nC\nA\nD\nE" | sed -n "/$var/!p"
-l: !p": event not found

El shell nos devuelve un mensaje de error ! Efectivamente, el ! es un carácter reservado del shell
que sirve para el historial de los comandos y no ha podido ser interpretado como tal.

Separemos la variable de la expresión propia a Sed encerrando la expresión justo antes de la


variable y volviéndola a abrir justo después utilizando apostrofes simples (observa que los
apóstrofos dobles alrededor de la variable son opcionales, pero que es preferible dejarlos, ya que es
una buena costumbre a considerar para prevenir posibles errores debidos a espacios dentro de la
variable).
$ var=A; echo -e "A\nB\nC\nA\nD\nE" | sed -n '/'"$var"'/!p'
B
C
D
E

Las expresiones regulares


El conocimiento de expresiones regulares (regexp) es un plus en la práctica de Sed (y de muchos
otros lenguajes)

Una expresión regular es un patrón (pattern en inglés) para buscar coincidencias con cadenas de
caracteres.

La potencia de las expresiones regulares radica en su capacidad de incluir alternativas y repeticiones


en la elaboración del patrón. Estas particularidades son elaboradas utilizando caracteres especiales,
que no son interpretados literalmente, sino de una manera especifica.

A continuación una breve descripción de la sintaxis de las expresiones regulares utilizadas en Sed.

carácter (cualquier carácter): Coincide con un carácter único.

* Coincide si el carácter o conjunto de caracteres que el precede está presente 0 o más veces. Puede
ser un carácter ordinario, un carácter especial protegido por un \, un punto (.), un grupo de
expresión regular o una subexpresión.

\+ Idéntico a *, pero indica que la expresión anterior puede ocurrir una o varias veces.

\? Idéntico a *, pero indica que la expresión anterior puede ocurrir 0 o 1 vez.

\{i\} Idéntico a *, pero coincide con exactamente i secuencia de la ocurrencia de la expresión


precedente (i representa un entero).

\{i,j\} Coincide con una secuencia comprendida entre i y j incluyéndolas.

\{i,\} Coincide con una secuencia mayor o igual a i.

\(regexp\) Coincide con un conjunto de expresiones regulares, llamado también subexpresión y que
puede ser direccionada por referencia hacia atrás (back referente).

. un punto: Cualquier carácter, excepto una nueva línea.

^ Coincide con una cadena nula al inicio de la línea, es decir lo que se encuentra después del acento
circunflejo debe aparecer al inicio de línea o al inicio de una subexpresión.

$ Idéntico a ^ pero la coincidencia es al final de la línea o subexpresión.

[lista] Coincide con cualquier carácter de la lista. Una lista puede estar constituida por una
secuencia de letras como [a-z] lo que equivale a una coincidencia con cualquier carácter
comprendido en a y z incluidos. Para incluir un ] hazlo figurar en primera posición en la lista. Para
incluir un - ponlo en la primera o ultima posición de la lista. Para incluir un ^ ponlo después del
primer carácter de la lista.

Por lo general, los caracteres $, *, ., [, y \ no son considerados como caracteres especiales dentro de
una lista. De este modo la expresión [\*] corresponderá tanto al carácter \ como al carácter *, el
carácter \ no es considerado como un carácter de escape para proteger el carácter *.

[^lista] A la inversa, un ^ al inicio de lista, hará coincidir con cualquier carácter excepto los de la
lista. Para incluir un ] hazlo figurar en la primera posición en la lista justo después de el signo ^.
regexp1\|regexp2 Coincidencia con regexp1 o regexp2. La búsqueda de coincidencias se hace con
cada una de las alternativas, de izquierda a derecha y la primera que es encontrada es utilizada.
Observa el carácter \ para proteger el carácter |.

\número Coincide con la enésima subexpresión \ (...\) utilizada en la expresión regular. Las
subexpresiones, llamadas también "referencias hacia a tras", son implícitamente numeradas de
izquierda a derecha contando el numero de ocurrencias de \(, con un máximo de 9.

\n Coincide con el carácter nueva línea (LF)

\métacaracter Coincide con un metacaracter entre $, *, ., [, \, o ^, debiendo ser protegido para una
interpretación literal.

Nota: En la búsqueda de una coincidencia, esta es efectuada de izquierda a derecha, y si dos o más
expresiones tienen el mismo carácter inicial, la coincidencia será hecha con la expresión más larga.

Los caracteres de escape


\a alarma (campana bip) (BEL, Ctrl-G, 0x07).

\b borrado hacia atrás (BS, Ctrl-H, 0x08).

\f fin de página (FF, Ctrl-L, 0x0C).

\n fin de línea (LF, Ctrl-J, 0x0A).

\r retorno de carro (CR, Ctrl-M, 0x0D).

\t tabulación horizontal (HT, Ctrl-I, 0x09).

\v tabulación vertical (VT, Ctrl-K, 0x0B)

\o000 carácter cuyo valor en el sistema octal es 000 (de una a tres cifras) [0-7]

\dDDD carácter cuyo valor en el sistema decimal es DDD (de una a tres cifras) [0-9]

\xHH carácter cuyo valor en el sistema hexadecimal es HH [0-9A-F]

Otros
\` coincide con una cadena nula al inicio de la línea (idéntico a ^).

' coincide con una cadena nula al final de la línea (idéntico a $).

\b coincide con una cadena vacía al extremo de una palabra. Denota el límite entre una palabra y un
carácter que no sea una palabra.
\B coincide con una cadena vacía que no se encuentre al extremo de una palabra. Denota el límite
entre un carácter, salvo una palabra, y una palabra.

\w cualquier palabra de la clase: [A-Za-z0-9_] (underscore _ incluido).

\W cualquier palabra que no pertenezca a la clase: [^A-Za-z0-9_] (underscore _ incluido)

\s cualquier carácter de espaciado: espacio, tabulación horizontal o vertical.

\S uno o varios caracteres de espaciado.

\< coincide con una cadena vacía al inicio de una palabra.

\> coincide con una cadena vacía al final de una palabra.

\e fin de conversión de mayúsculas o minúsculas.

\l conversión del próximo carácter en minúscula.

\L conversión de los caracteres restantes en minúscula.

\u conversión del próximo carácter en mayúscula.

\U conversión de los caracteres restantes en mayúscula.

Las clases de caracteres


[:alnum:] caracteres alfanuméricos [A-Za-z0-9]

[:alpha:] caracteres alfabéticos [A-Za-z]

[:digit:] cifras [0-9]

[:lower:] caracteres en minúsculas [a-z]

[:upper:] caracteres en mayúsculas [A-Z]

[:print:] caracteres imprimibles [ -~]

[:punct:] caracteres de puntuación [!-/:-@[-`{-~]

[:space:] espacios, tabulaciones y cualquier carácter vacío [ \t\v\f].

[:blank:] espacio y tabulación [ \x09].

[:graph:] cualquier carácter imprimible [!-~] (excepto los espacios vacíos).


[:cntrl:] caracteres de control [\x00-\x19\x7F].

[:xdigit:] números hexadecimales [0-9a-fA-F].

Las diferentes versiones


Unix
GNU sed v4.0.5 (Gsed) Descarga. Ultima versión oficial de GNU Sed ofreciendo la edición actual
(-i).

Ssed v3.60 Descarga. (Small/Stupid Stream EDitor) Versión recomendada

BSD multi-byte sed Descarga (Japonesa basada en la ultima versión de GNU Sed).

Windows
GnuWin32-Sed v4.1.5 Descargar. La versión ejecutable para MS Windows 95 / 98 / ME / NT /
2000 y XP.

Depuradores
A continuación 2 depuradores que te permitirán comprender mejor el funcionamiento de Sed y, en
algunos casos, te ahorrarán enormes horas de trabajo.
sd.ksh y sd.sh.txt son dos pequeños scripts escritos en Korn shell y Bourne shell respectivamente
que incluyen un manual de uso al final del fichero.

sedsed está escrito en Python (por lo que debe ser instalado en tu sistema) y te permite visualizar el
estado del buffer y los comandos interpretados.

A continuación un mini tutorial para el uso de sedsed.


Usage : sedsed OPTION [-e sedscript] [-f sedscriptfile] [inputfile]
OPCIONES:
-f, --file lectura de los comandos desde el fichero indicado
-e, --expression permite encadenar varios comandos
-n, --quiet solicitud implicita para no mostrar el estado de la
memoria principal
--silent equivalente a --quiet
-d, --debug activa el modo debug
--hide oculta ciertas opciones de depuración (opciones:
PATT,HOLD,COMM)
--color activa la salida del depurador coloreado (activado por
defecto)
--nocolor desactiva la salida del depurador coloreado
--dump-debug listado del depurador en la pantalla
-i, --indent indentación del script, un comando por línea
--prefix indentación precedida por espacios o tabulaciones (4
espacios por defecto)
-t, --tokenize modo verbosa, muestra cada comando con más información
-H, --htmlize convierte un script sed en una página HTML coloreada
-V, --version muestra la versión del programa y termina
-h, --help muestra una página de ayuda y termina

Significado a la salida:
PATT: Muestra el contenido del espacio patrón (memoria principal).
HOLD: Muestra el contenido de la memoria secundaria.
COMM: El comando SED debe ser ejecutado.
$ Delimita el contenido de PATT y HOLD.

La sintaxis más común es el modo debug simple (-d):


echo -e "AAA\nBBB\nCCC\nDDD" | sed '/BBB/ {n;s/C/Z/2}'
echo -e "AAA\nBBB\nCCC\nDDD" | sedsed -d '/BBB/ {n;s/C/Z/2}'

<a href='http://www.commentcamarche.net/faq/images/0-B4IoZAnt-debogage-d.png'><a
href='http://www.commentcamarche.net/faq/images/0-B4IoZAnt-debogage-d.png'>

</a></a>
Esquema: debogage_-d.png

En modo indentación:
sedsed -i -n ':notag;/tag/!{1!H;1h;x;s/\n/ /g;x;$b lastline;d;};/tag/{x;/^$/!p;
$b lastline;d;b notag;};:lastline;x;p;'
Esquema: debogage_indent.png

Ocultar la visualización de la memoria secundaria:


echo -e "AAA\nBBB\nCCC\nDDD" | sedsed -d --hide=HOLD -n '/BBB/ {n;s/C/Z/2p}'

Cuando no debo utilizar Sed


Cuando ya existen herramientas apropiadas y efectúan la tarea fácilmente y con mayor rapidez, por
ejemplo:
Búsqueda de patrón simple:

grep "patrón" fichero # sed -n "/patrón/p' fichero

Exclusión de un patrón simple:

grep -v "patrón" fichero # sed "/patrón/!d' fichero

Búsqueda de patrón y visualización de líneas de contexto antes/después:

grep -A1 -B1 "patón" fichero # sed -n '/patrón/! {x;d;}; /patrón/{x;p;x;p;n;p;x;}' fichero

Numeración de líneas:

cat -n fichero # sed -e '=' fichero | sed 'N;s/\n/\t/'

nl fichero

Eliminación de saltos de línea


tr '\n' ' ' < fichero# sed ':bucle; N; $! b bucle; s/\n//g' fichero

Eliminación de caracteres individuales

tr -d "[w-z]" < fichero # sed 's/[w-z]//g' fichero

Repetición de caracteres

echo "Booonjoouuur" | tr -s "ou" # echo "Booonjoouuur" | sed 's/oo*/o/g;s/uu*/u/'

Transposición de caracteres

echo "ABCDEF" | tr "[A-F]" "[a-f]" # echo "ABCDEF" | sed 'y/ABCDEF/abcdef/'

Formato de ficheros, mejor utilizar los comandos:


fold, fmt y par.

Para ciertas tareas que awk y perl las realizan mucho mas fácil y rápido, como por ejemplo: contar
campos y caracteres, contar líneas de un bloque u objetos de un fichero, operaciones matemáticas,
calcular la longitud de una cadena, manipular datos binarios, bucles en tablas o listas, etc.

Limites conocidos de las diferentes versiones


A continuación algunos límites conocidos de las versiones distribuidas de Sed, dependiendo claro
estas del hardware, la memoria, el sistema operativo y de las librerías C utilizadas durante la
compilación de Sed.
Longitud máxima de una línea:

GNU sed: sin limitación


ssed: sin limitación

Tamaño máximo de la memoria principal y secundaria:

GNU sed: sin limitación


ssed: sin limitación

Número máximo de ficheros que pueden ser leídos por el comando "r":

GNU sed v3+: sin limitación


ssed: sin limitación
GNU sed v2.05: el total de lecturas (r) y escrituras (w) no debe exceder 32.

Numero máximo de ficheros que pueden ser escritos por el comando "w":

GNU sed v3+: sin limitación


ssed: sin limitación
GNU sed v2.05: el total de lecturas (r) y escrituras (w) no debe exceder 32.

Tamaño máximo de un nombre de etiqueta

GNU sed: sin limitación


ssed: sin limitación
BSD sed: 8 caracteres

Tamaño máximo de nombre de fichero en escritura

GNU sed: sin limitación


ssed: sin limitación
BSD sed: 8 caracteres

Numero máximo de conexiones

GNU sed: sin limitación


ssed: sin limitación

Anda mungkin juga menyukai