Del espacio de Patrones al de Mantenimiento

En sed se dispone, como en muchos otros editores de una zona de memoria a la que se puede enviar texto ``cortado'' o `copiado'' y desde la cual se puede recuperar el texto para insertarlo en la zona de trabajo (pattern space). en la jerga sed dicho espacio se conoce como hold space. El contenido del espacio de patrones (pattern space) puede moverse al espacio de mantenimiento (hold space) y recíprocamente:




Hold h ó H Copia o añade (append) los contenidos del pattern space al hold space.
Get g ó G Copia o añade los contenidos del hold space al pattern space.
Exchange x Intercambia los contenidos del hold space y el pattern space



Los comandos en minúsculas sobrescriben mientras que los que van en mayúsculas añaden. Asi h copia los contenidos del pattern space en el hold space, borrando los contenidos previos que estuvieran en el hold space. Las orden G añade (paste) los contenidos del hold space al espacio de patrones actual (por el final). Las dos cadenas se enlazan a través de un retorno de carro.

Ejemplo Este guión intenta mediante una heurística poner la definiciones de funciones C al final del fichero, suponiendo que una definición de función comienza en la columna 1 y que se caracterizan mediante uno o dos identificadores seguidos de un paréntesis:

$ cat G.sed
/\<if\>/s/.*/&/
t
/\<else\>/s/.*/&/
t
#... lo mismo para las otras palabras clave
/^[a-zA-Z][a-zA-Z]*([A-Z]*/H
t
/^[a-zA-Z][a-zA-Z]*  *[a-zA-Z][a-zA-Z]*(/H
${
G
}
Ejemplo de uso:
$ cat p.test
#include <stdio.h>
 
fact(int n) { /* recursive function */
if(n == 0) return 1;
else(return n*fact(n-1));
}
 
void toto(id) {
}
 
main() {
  toto();
  printf("Hello world! factorial of 4 = %d\n",fact(4)); /* the
         comment takes two lines */
}
Al ejecutar nuestro script obtenemos la salida:
$ sed -f G.sed p.test
#include <stdio.h>
 
fact(int n) { /* recursive function */
if(n == 0) return 1;
else(return n*fact(n-1));
}
 
void toto(id) {
}
 
main() {
  toto();
  printf("Hello world! factorial of 4 = %d\n",fact(4)); /* the
         comment takes two lines */
}
 
fact(int n) { /* recursive function */
void toto(id) {
main() {

Ejemplo El siguiente guión invierte los contenidos de un fichero:

> cat reverse.sed
$!{
:loop
h
n
G
$!b loop
}
${
p
}
He aqui el resultado de una ejecución:

> cat reverse.test
one
two
three
> sed -n -f reverse.sed reverse.test
three
two
one

Ejemplo

Supuesto un fichero de entrada con formato: ...

NAME: xxx
SURNAME: xxx
TITLE: SISTEMAS
OtherTitle: 
BIRTHDAY: xxx
BIRTHMONTH: xxx
BIRTHYEAR: xxx
ADDRESSFAMILY: xxx
ADDRESSACTUAL: xxx
POSTALCODE: xxx
EMAIL: XXXXXXX@csi.ull.es
TELEPHONE: xxx
FAX: xxx
LABGROUP: xxx
COMMENTS:
...

Se pretenden extraer los apellidos y el nombre, concatenados con una coma. He aqui una posible solución:

#!/bin/sed -f
/^NAME:/ {
  s/^NAME://
  h
  n
  s/^SURNAME://
  G
  s/\n/,/
  y/áéíóúabcdefghijklmnñopqrstuvwxyz/ÁÉÍÓÚABCDEFGHIJKLMNÑOPQRSTUVWXYZ/
  p
}

Casiano Rodríguez León
2013-04-23