sed ("editor de secuencias") es una utilidad de Unix que analiza y transforma texto, utilizando un lenguaje de programación simple y compacto. Fue desarrollado entre 1973 y 1974 por Lee E. McMahon de Bell Labs , [1] y está disponible hoy en día para la mayoría de los sistemas operativos. [2] sed se basó en las características de scripting del editor interactivo ed ("editor", 1971) y el anterior qed ("editor rápido", 1965-66). Fue una de las primeras herramientas en soportar expresiones regulares , y sigue en uso para el procesamiento de texto, más notablemente con el comando de sustitución. Las herramientas alternativas populares para la manipulación de cadenas de texto sin formato y la "edición de secuencias" incluyen AWK y Perl .
Apareciendo por primera vez en la versión 7 de Unix , [3] sed es uno de los primeros comandos de Unix creados para el procesamiento de archivos de datos desde la línea de comandos. Evolucionó como el sucesor natural del popular comando grep . [4] La motivación original fue un análogo de grep (g/re/p) para la sustitución, de ahí "g/re/s". [3] Previendo que también surgirían otros programas de propósito especial para cada comando, como g/re/d, McMahon escribió un editor de flujo orientado a líneas de propósito general, que se convirtió en sed. [4] La sintaxis de sed, en particular el uso de /
para la coincidencia de patrones y s///
para la sustitución, se originó con ed , el precursor de sed, que era de uso común en ese momento, [4] y la sintaxis de expresiones regulares ha influido en otros lenguajes, en particular ECMAScript y Perl . Más tarde, se desarrolló el lenguaje más poderoso AWK , y estos funcionaron como primos, lo que permitió que se realizara un procesamiento de texto potente mediante scripts de shell . sed y AWK se citan a menudo como progenitores e inspiración para Perl, e influyeron en la sintaxis y la semántica de Perl, especialmente en los operadores de coincidencia y sustitución.
GNU sed agregó varias características nuevas, incluyendo la edición de archivos en el lugar. Super-sed es una versión extendida de sed que incluye expresiones regulares compatibles con Perl . Otra variante de sed es minised , originalmente diseñada a la inversa a partir de sed 4.1BSD por Eric S. Raymond y actualmente mantenida por René Rebe . minised fue utilizado por el Proyecto GNU hasta que el Proyecto GNU escribió una nueva versión de sed basada en la nueva biblioteca de expresiones regulares de GNU. El minised actual contiene algunas extensiones de sed BSD pero no es tan rico en características como sed GNU. Su ventaja es que es muy rápido y utiliza poca memoria. Se utiliza en sistemas embebidos y es la versión de sed proporcionada con Minix . [5]
sed es una utilidad de procesamiento de texto orientada a líneas: lee texto, línea por línea, desde un flujo de entrada o archivo, en un búfer interno llamado espacio de patrones . Cada línea leída inicia un ciclo . Al espacio de patrones, sed aplica una o más operaciones que se han especificado mediante un script sed . sed implementa un lenguaje de programación con aproximadamente 25 comandos que especifican las operaciones sobre el texto. Para cada línea de entrada, después de ejecutar el script, sed normalmente genera el espacio de patrones (la línea modificada por el script) y comienza el ciclo nuevamente con la línea siguiente. Otros comportamientos de fin de script están disponibles a través de las opciones de sed y los comandos de script, por ejemplo, d
eliminar el espacio de patrones, q
salir, N
agregar la siguiente línea al espacio de patrones inmediatamente, etc. Por lo tanto, un script sed corresponde al cuerpo de un bucle que itera a través de las líneas de un flujo, donde el bucle en sí y la variable de bucle (el número de línea actual) son implícitos y mantenidos por sed.
El script sed puede especificarse en la línea de comandos ( -e
opción) o leerse desde un archivo separado ( -f
opción). Los comandos en el script sed pueden tomar una dirección opcional, en términos de números de línea o expresiones regulares . La dirección determina cuándo se ejecuta el comando. Por ejemplo, 2d
solo ejecutaría el d
comando (delete) en la segunda línea de entrada (imprimiendo todas las líneas excepto la segunda), mientras que /^ /d
eliminaría todas las líneas que comiencen con un espacio. Un búfer especial separado, el espacio de retención , puede ser utilizado por algunos comandos sed para retener y acumular texto entre ciclos. El lenguaje de comandos de sed tiene solo dos variables (el "espacio de retención" y el "espacio de patrones") y una funcionalidad de ramificación similar a GOTO ; sin embargo, el lenguaje es Turing-completo , [6] [7] y existen scripts sed esotéricos para juegos como sokoban , arkanoid , [8] ajedrez , [9] y tetris . [10]
Un bucle principal se ejecuta para cada línea del flujo de entrada, evaluando el script sed en cada línea de la entrada. Cada línea de un script sed es un par patrón-acción, que indica qué patrón hacer coincidir y qué acción realizar, lo que puede reformularse como una declaración condicional . Debido a que el bucle principal, las variables de trabajo (espacio de patrones y espacio de retención), los flujos de entrada y salida y las acciones predeterminadas (copiar línea al espacio de patrones, imprimir espacio de patrones) son implícitos, es posible escribir programas concisos de una sola línea . Por ejemplo, el programa sed dado por:
10q
imprimirá las primeras 10 líneas de entrada y luego se detendrá.
El siguiente ejemplo muestra un uso típico y más común de sed: la sustitución. Este uso fue, de hecho, la motivación original de sed: [4]
sed 's/regexp/replacement/g' nombreArchivoEntrada > nombreArchivoSalida
En algunas versiones de sed, la expresión debe ir precedida de -e
para indicar que sigue una expresión. El s
significa sustituto, mientras que el g
significa global, lo que significa que se reemplazarán todas las ocurrencias coincidentes en la línea. La expresión regular (es decir, patrón) que se buscará se coloca después del primer símbolo delimitador (barra oblicua aquí) y el reemplazo sigue al segundo símbolo. La barra oblicua ( /
) es el símbolo convencional, que se origina en el carácter para "buscar" en ed, pero se puede usar cualquier otro para hacer que la sintaxis sea más legible si no aparece en el patrón o reemplazo; esto es útil para evitar el " síndrome del palillo inclinado ".
El comando de sustitución, que se origina en la función de búsqueda y reemplazo en ed, implementa un análisis y una creación de plantillas simples . regexp
Proporciona coincidencia de patrones y guarda texto mediante subexpresiones, mientras que replacement
puede ser texto literal o una cadena de formato que contenga los caracteres &
para "coincidencia completa" o las secuencias de escape \1
especiales hasta \9
para la n.ª subexpresión guardada. Por ejemplo, sed -r "s/(cat|dog)s?/\1s/g"
reemplaza todas las ocurrencias de "gato" o "perro" con "gatos" o "perros", sin duplicar una "s" existente: (cat|dog)
es la primera (y única) subexpresión guardada en la expresión regular y, \1
en la cadena de formato, la sustituye en la salida.
Además de la sustitución, existen otras formas de procesamiento simple que se pueden realizar mediante el uso de unos 25 comandos sed. Por ejemplo, el siguiente comando utiliza el comando d para filtrar líneas que solo contienen espacios o que solo contienen el carácter de fin de línea:
sed '/^ *$/d' nombreArchivoEntrada
Este ejemplo utiliza algunos de los siguientes metacaracteres de expresiones regulares (sed admite la gama completa de expresiones regulares):
^
) coincide con el comienzo de la línea.$
) coincide con el final de la línea.*
) coincide con cero o más ocurrencias del carácter anterior.+
) coincide con una o más ocurrencias del carácter anterior.?
) coincide con cero o una ocurrencia del carácter anterior..
) coincide exactamente con un carácter.Son posibles construcciones sed complejas, lo que le permite servir como un lenguaje de programación simple, pero altamente especializado . El flujo de control, por ejemplo, se puede gestionar mediante el uso de una etiqueta (dos puntos seguidos de una cadena) y la instrucción de bifurcación b
, así como la bifurcación condicional t
. Una instrucción b
seguida de un nombre de etiqueta válido moverá el procesamiento al comando que sigue a esa etiqueta. La t
instrucción solo lo hará si hubo una sustitución exitosa desde la anterior t
(o el inicio del programa, en caso de la primera t
encontrada). Además, la {
instrucción inicia una subsecuencia de comandos (hasta el }
); en la mayoría de los casos, estará condicionada por un patrón de dirección.
En Unix, sed se utiliza a menudo como filtro en una canalización :
$ generarDatos | sed 's/x/y/g'
Es decir, un programa como "generateData" genera datos y luego sed realiza el pequeño cambio de reemplazar x por y . Por ejemplo:
$ echo xyz xyz | sed 's/x/y/g' yyz yyz
[notas 1]
A menudo resulta útil colocar varios comandos sed, un comando por línea, en un archivo de script como subst.sed
, y luego usar la -f
opción para ejecutar los comandos (como s/x/y/g
) desde el archivo:
sed -f subst.sed nombreArchivoEntrada > nombreArchivoSalida
Se puede colocar cualquier cantidad de comandos en el archivo de script, y el uso de un archivo de script también evita problemas con el escape o las sustituciones del shell.
Un archivo de script de este tipo se puede ejecutar directamente desde la línea de comandos si se le antepone una " línea shebangsubst.sed
" que contenga el comando sed y se le asigna el permiso de ejecución. Por ejemplo, se puede crear un archivo con el contenido siguiente:
#!/bin/sed -fs / x / y / g
El usuario actual podrá luego hacer que el archivo sea ejecutable con el chmod
comando:
chmod u+x subst.sed
El archivo puede luego ejecutarse directamente desde la línea de comando:
subst.sed nombreArchivoEntrada > nombreArchivoSalida
La -i
opción, introducida en GNU sed, permite la edición de archivos en el lugar (en realidad, se crea un archivo de salida temporal en segundo plano y luego el archivo original se reemplaza por el archivo temporal). Por ejemplo:
sed -i 's/abc/def/' nombreArchivo
# convierte el flujo de texto de entrada a "¡Hola, mundo!" s / .* / ¡Hola, mundo! / q
Este script "¡Hola, mundo!"sed -f script.txt inputFileName
está en un archivo (por ejemplo, script.txt) y se invoca con , donde "inputFileName" es el archivo de texto de entrada. El script cambia la línea n.° 1 de "inputFileName" por "¡Hola, mundo!" y luego se cierra, imprimiendo el resultado antes de que sed salga. Las líneas de entrada posteriores a la línea n.° 1 no se leen ni se imprimen. Por lo tanto, la única salida es "¡Hola, mundo!".
El ejemplo resalta muchas características clave de sed:
#
símbolo).s
comando (sustituto) es el comando sed más importante.q
(salir)..*
(cero o más de cualquier carácter).A continuación se muestran varios scripts sed; estos pueden ejecutarse pasándolos como argumento a sed, o colocándolos en un archivo separado y ejecutándose a través de -f
o haciendo que el script en sí sea ejecutable.
Para reemplazar cualquier instancia de una determinada palabra en un archivo con "REDACTADO", como una contraseña de IRC, y guardar el resultado:
$ sed -i "s/tucontraseña/REDACTADA/" ./status.chat.log
Para eliminar cualquier línea que contenga la palabra "tupalabra" (la dirección es '/tupalabra/'):
/ tupalabra / d
Para eliminar todas las instancias de la palabra "tupalabra":
s / tupalabra // g
Para eliminar dos palabras de un archivo simultáneamente:
s / primera palabra // g s / segunda palabra // g
Para expresar el ejemplo anterior en una línea, como al ingresar en la línea de comando, se pueden unir dos comandos mediante el punto y coma:
$ sed "s/primerapalabra//g; s/segundapalabra//g" nombreArchivoEntrada
En el siguiente ejemplo, sed, que normalmente solo funciona en una línea, elimina los saltos de línea de las oraciones en las que la segunda línea comienza con un espacio. Considere el siguiente texto:
Este es mi perro, cuyo nombre es Frank.Este es mi pez,cuyo nombre es George.Esta es mi cabra, cuyo nombre es Adán.
El script sed que aparece a continuación convertirá el texto anterior en el siguiente. Tenga en cuenta que el script afecta únicamente a las líneas de entrada que comienzan con un espacio:
Este es mi perro, cuyo nombre es Frank.Este es mi pez,cuyo nombre es George.Esta es mi cabra, cuyo nombre es Adán.
El guión es:
N s / \n / / P D
Esto se explica así:
N
) agrega la siguiente línea al espacio del patrón;s/\n / /
) busca una nueva línea seguida de un espacio, reemplaza con un espacio;P
) imprime la línea superior del espacio del patrón;D
) elimine la línea superior del espacio de patrones y ejecute el script nuevamente.Esto se puede expresar en una sola línea mediante punto y coma:
sed ' ' nombreArchivoEntradaN; s/\n / /; P; D
Aunque es simple y limitado, sed es lo suficientemente potente para una gran cantidad de propósitos. Para un procesamiento más sofisticado, se utilizan lenguajes más potentes como AWK o Perl . Estos se utilizan particularmente si se transforma una línea de una manera más complicada que una extracción de expresiones regulares y un reemplazo de plantilla, aunque en principio es posible realizar transformaciones arbitrariamente complicadas utilizando el búfer de retención.
Por el contrario, para operaciones más sencillas, suelen ser preferibles utilidades especializadas de Unix como grep (imprime líneas que coinciden con un patrón), head (imprime la primera parte de un archivo), tail (imprime la última parte de un archivo) y tr (traduce o elimina caracteres). Para las tareas específicas para las que están diseñadas, estas utilidades especializadas suelen ser más sencillas, claras y rápidas que una solución más general como sed.
Los comandos y la sintaxis de ed/sed siguen utilizándose en programas descendientes, como los editores de texto vi y vim . Un análogo de ed/sed es sam /ssam, donde sam es el editor de Plan 9 y ssam es una interfaz de flujo para él, que ofrece una funcionalidad similar a sed.
s/x/y/g
no hay ambigüedad, por lo que generateData | sed s/x/y/g
funciona correctamente. Sin embargo, las comillas se incluyen generalmente para mayor claridad y a menudo son necesarias, especialmente para espacios en blanco (por ejemplo, 's/x x/y y/'
). La mayoría de las veces se utilizan comillas simples para evitar que el shell interprete $
como una variable del shell. Se utilizan comillas dobles, como "s/$1/$2/g"
, para permitir que el shell sustituya un argumento de la línea de comandos u otra variable del shell.Un tiempo después surgió la demanda de otro programa de propósito especial, gres, para la sustitución: g/re/s. Lee McMahon se encargó de escribirlo y pronto previó que la familia no tendría fin: g/re/d, g/re/a, etc. A medida que su concepto se fue desarrollando, se convirtió en algo habitual…