Copyright © 2005-2024 LinuxTotal.com.mx
Se concede permiso para copiar, distribuir y/o modificar este documento siempre y cuando se cite al autor y la fuente de linuxtotal.com.mx y según los términos de la GNU Free Documentation License, Versión 1.2 o cualquiera posterior publicada por la Free Software Foundation.
Artículo original en inglés: The Basics of Using the Sed Stream Editor to Manipulate Text in Linux por: Justin Ellingwood
El editor en línea (stream editor) sed
es un editor de texto en línea que realiza operaciones de edición sobre datos provenientes desde un archivo o desde el "standard input" (Entrada de datos estandar mejor conocido como teclado). sed
edita línea por línea en un modo no interactivo.
Esto quiere decir que tu realizas todas las decisiones de edición conforme se ejecuta el comando y sed
ejecuta las directivas automáticamente. Esto resulta confuso o poco intuitivo, pero es un modo muy poderoso y un método rápido para transforma text.
Este tutorial de sed
tratará sobre operaciones básicas y te presentará la sintaxis requerida para operar este editor. Ciertamente nunca reemplazarás tu editor de texto regular (como vim
) con sed
, pero muy probabblemente, una vez que aprendas su facilidad de uso, será una addición bienvenida a tus herramientas de edición de texto.
De maneral general, sed
opera sobre un flujo de texto que es leido desde un archivo o desde "standard input". Esto quiere decir que se puede enviar la salida de un comando directamente a sed
para ser editado o tu puedes indicar un archivo que ya este previamente creado.
Por otro lado, el resultado o salida de sed
es enviado por default a la pantalla. O si es redireccionado será enviado a la archivo que indiques.
Modos básicos es:
$ sed [opciones] comandos [archivo_a_editar] $ sed [opciones] comandos archivo > archivo_de_salida $ otro_comado | sed [opciones] comandos $ otro_comado | sed [opciones] comandos > archivo_de_salida
Para practicar lo anterior, copiemos algunos archivos en nuestro directorio HOME para practicar con sed
.
cd cp /usr/share/common-licenses/BSD . cp /usr/share/common-licenses/GPL-3 .
Ya que sabemos que sed
envia su resultado a la pantalla por default, podemos usarlo como un visor (o lector) de archivos al no pasarle "comandos" de edición, veamos:
$ sed '' BSD Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ... ...
Esto funciona porque enntre las comillas simples se indican los comandos de edición que se le pasan a sed
. Al no pasarle o innicarle nada entonces tan solo imprime cada línea que recibe a la pantalla (standard output).
Veamos como sed
puede usar el "standard input" al canalizar (piping) la salida del comando cat
hacía sed
para producir el mismo resultado mostrado anteriormente:
$ cat BSD | sed '' Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. ... ...
Como se puede ver, podemos trabajar igual de fácil con archivos o con flujos de texto , como el que se produce cuando canalizamos la salida de cat
con "|" pipe.
En el ejemplo previo, vimos como al pasar un archivo o flujo de texto al comando sed
sin ningún comando, imprime el resultado directamente a la pantalla (standard output).
El primer comando que aprenderemos será el comando p dentro de las comillas sencillas:
$ sed 'p' BSD Copyright (c) The Regents of the University of California. Copyright (c) The Regents of the University of California. All rights reserved. All rights reserved. Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions ... ...
Se puede observar que sed
imprimió cada línea dos veces. Esto es porque de manera automática sed
ya imprime cada línea, y entonces al añadir el comando p le estamos diciendo que imprima explícitamente cada línea.
Este ejemplo es importante para entender como trabaja sed
. Si se examina como la salida tiene la primera línea dos veces, y después la segunda línea igual, dos veces, etc. se entenderá entonces que sed
opera siempre línea por línea. Es decir, acepta una línea, opera en ella con el o los comandos indicados y después muestra el texto resultante en la salida antes de operar con la siguiente línea.
Podemos limpiar el resultado al indicar la opción -n que suprime la impresión automática de líneas.
$ sed -n 'p' BSD Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: ... ...
Ahora solo vemos la impresión de solo una línea a la vez.
Este último ejemplo también muestra un ejemplo de sed
completo:
$ sed -n 'p' BSD $ sed [opciones] comandos archivo_de_texto
Los ejemplos mostrados hasta ahora no pueden ser considerados de edición (solo que la intención sea explícitamente imprimir cada renglón dos veces). Modificquemos ahora la salida indicándole a sed
que solo deseamos imrimir la prímera línea.
$ sed -n '1p' BSD Copyright (c) The Regents of the University of California.
Al colocar el número "1" antes del comando imprimir p (print), le estamos indicando a sed
explícitamente sobre que línea operar. Si queremos operar sobre un rango de líneas maor, por ejemplo las primeras 5 líneas, podemos fácilmente indicarlo de la siguiente manera (no olvides la opción -n) :
$ sed -n '1,5p' BSD Copyright (c) The Regents of the University of California. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions
Le hemos indicado a sed
un rango de direcciones (address range), o mas entendible, un rango de renglones sobre los cuales operar. Al indicar un rango, solo se ejecutaran los comandos en esas líneas específicas del rango. en este último ejemplo de la línea 1 a la 5.
Otro modo de lograr exactamente el mismo resultado es indicando el renglón o rango inicial y entonces indicar un número de desplazamiento (offset) para indicarle a sed
cuantas líneas adicionales utilizar.
$ sed -n '1,+4p' BSD $ sed -n '1,5p' BSD
Si lo que deseas es imprimir cada otra línea, o cada 2 líneas, se indica el caracter ~ (tilde) para esto. seguido del número de cada x líneas imprimir, veamos con ejemplos:
$ sed -n '1~2p' archivo_de_texto $ sed -n '7~3p' archivo_de_texto
Se puede fácilmente realizar operaciones de borrado o eliminación de texto tan solo cambiando el comando p por el comando d (delete, borrar en inglés).
Cuando se trabaja con el comando d ya no es necesario indicar la opción -n porque al utilizar el comando "delete" sed
mostrará en pantalla (por default) todo lo que NO ha sido eliminado, que ayuda a darse cuenta que esta sucediendo.
Podemos modificar uno de los últimos ejemplos de la sección anterior para que elimine cada otra línea empezando por la primera. El resultado es que nos debe mostrar las líneas que NO fueran dadas con el comando p:
$ sed '1~2d' BSD ll rights reserved. Redistribution and use in source and binary forms, with or without are met: notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer in the 3. Neither the name of the University nor the names of its contributors without specific prior written permission. ... ... $ sed '4d' BSD (Elimina la línea 4, pero resultado en pantalla es que se mostrará las líneas 1 a 3 y de la 5 en delante)
En los dos ejemplos previos, es muy IMPORTANTE hacer notar que el archivo original no esta siendo afectado en lo absoluto, continua intacto, nada se eliminó en el original. Las ediciones o eliminaciones de línea en este caso, son el resultado enviado a pantalla
Antes de ver como funciona la opción -i recrodemos que es muy fácil guardar tus ediciones con sed
redirigiendo la salida estandar (standard output) a un archivo.
$ sed '1~2d' BSD > everyother.txt
Si abrimos este archivo con cat
o more
veremos la misma salida que vimos en la pantalla previamente. Por nuestra seguridad sed
no edita el documento fuente, como ya se mencionó.
Se puede cambiar este comportamiento indicando la opción -i (in-place), que efectivamente editará el documento de texto fuente u original.
Editemos el archivo "everyother.txt" que acabamos de crear con la opción in-place -i, reduciendo el archivo al eliminar cada otra línea de nuevo.
$ sed -i '1~2d' everyother.txt
Si usamos cat
de nuevo, podrás ver que el archivo fue efectivamente editado.
El uso de la opción -i puede ser peligrosa. Afortunadamente, sed
nos da la opción de crear un respaldo del archivo antes de editar el mismo.
$ sed -i.bkp '1~2d' everyother.txt
Esto creará un archivo de respaldo (backup) con la extensión ".bkp" y solo después editará el archivo indicado. Por supuesto que puedes indicar lo que gustes como extensión.
Quizás el uso más conocido de sed
es la sustitución de texto. sed
tiene la habilidad de buscar por patrones de texto usando expresiones regulares y sustituir o reemplazar el text encontrado.
En su forma más simple, es posible sustituir una palabra por otra usando la siguiente sintaxis:
's/una_palabra/otra_palabra/' 's/buscar_un_patrón/sustituir_por_otro_patrón/'
s es el comando que indica "sustituir" o reemplazar. Las 3 diagonales / son usadas para separas los distintos campos. Es posible cualquier otro caracter para delimitar los campos (el que siga del comando s) si eso es más conveniente según el caso.
Por ejemplo, si estamos cambiando el nombre de un ditio web, entonces utilizar otro delimitador será más conveniente ya que los URLs contienen diagonales. En este ejemplo utilizaremos _ en vez de / como delimitador. Y también usaremos el comando echo
para canalizar | (pipe) su salida a sed
$ echo "http://www.example.com/index.html" | sed 's_com/index_org/home_' http://www.example.org/home.html
No hay que olvidar el último delimitador o sed
se quejará:
$ echo "http://www.example.com/index.html" | sed 's_com/index_org/home' sed: -e expression #1, char 22: unterminated `s' command
Vamos a crear un archivo donde podamos practicar sustituciones:
echo "this is the song that never ends yes, it goes on and on, my friend some people started singing it not knowing what it was and they'll continue singing it forever just because..." > annoying.txt
Sustituyamos la expresión "on" por "forward".
$ sed 's/on/forward/' annoying.txt this is the sforwardg that never ends yes, it goes forward and on, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...
Podemos observar algunas cosas notables con este ejemplo. Primero, estamos reemplazando patrones no palabras, esto se aprecia en el tercer cambio, el "on" dentro de "song" fue cambiado a "forward".
La otra cosa a notar es que en el cambio 2, el segundo "on" no fue sustituido por "forward".
Esto es porque por defecto, el comando s opera solo en la primera ocurrencia de cada línea y entonces pasa a la siguiente línea.
Para lograr que sed
reemplace cada instancia de "on" en vez de solo la primera ocurrencia, podemos entonces indicar una bandera o flag opcional al comando de sustitución s.
Indicaremos entonces para esto la bandera g (de global) al comanndo s al colocarlo después del conjunto de sustituciones:
$ sed 's/on/forward/g' annoying.txt this is the sforwardg that never ends yes, it goes forward and forward, my friend some people started singing it not knowing what it was and they'll cforwardtinue singing it forever just because...
Ahora el comando sustitución s ha cambiado cada instancia.
Si solo quisieramos cambiar la segunda instancia de "on" que sed
encuentre para cada línea, usaremos entonces el número 2 como bandera en vez de la bandera g.
$ sed 's/on/forward/2' annoying.txt this is the song that never ends yes, it goes on and forward, my friend some people started singing it not knowing what it was and they'll continue singing it forever just because...
Para ebitar toda la salida y solo ver las líneas donde hubo reemplazos, podemos usar la opción -n de nuevo para suprimir la impresión automática y además añadimos la bandera p (de Printing) para imprimir las líneas donde la sustitución se realizó.
$ sed -n 's/on/forward/2p' annoying.text yes, it goes on and forward, my friend
Como se puede observar, es posible combinar banderas o flags al final del comando.
sed
por defecto es sensible a mayúsculas y minúsculas. Si queremos que en el proceso de búsqueda de patrones se ignore esto, entonces podemos utilizar la bandera o flag i (de ignorar) que hace aso omiso en la búsqueda de mayúsculas y minúsculas.
$ sed 's/SINGING/saying/i' annoying.txt this is the song that never ends yes, it goes on and on, my friend some people started saying it not knowing what it was and they'll continue saying it forever just because...
Si lo que se desea es encontrar patrones (patterns) complejos con expresiones regulares, tenemos diferentes métodos de referenciar el patrón encontrado o igualado en el texto de reemplazo.
Por ejemplo, si queremos igualar desde el principio de la línea hasta el patrón "at", podemos usar la expresión:
$ sed 's/^.*at/REPLACED/' annoying.txt REPLACED never ends yes, it goes on and on, my friend some people started singing it REPLACED it was and they'll continue singing it forever just because...
/^.*at/ recuérdese que esta parte indica el patrón a buscar. ^ indica inicio o principio de línea. . indica cualquier tipo de caracter alfanumérico, espacios, símbolos. * indica cualquier número de caracteres (o ninguno) del símbolo que precede, en este caso .* quiere decir cualquier cantidad de caracteres. En español: ^.*at encuentra cualquier cadena de caracteres desde el inicio de línea hasta donde encuentre un "at".
Ya que no sabemos la frase exacta que será encontrada en la cadena de búsqueda, se puede utilizar el caracter & que representa el texto encontrado en la parte de reemplazo.
El siguiente ejemplo muestra como poner paréntesis alrededor del texto encontrado.
$ sed 's/^.*at/(&)/' annoying.txt (this is the song that) never ends yes, it goes on and on, my friend some people started singing it (not knowing what) it was just because...
Un modo más flexible de referenciar el texto encontrado es usar paréntesis con escape \ para agrupar en secciones el texto encontrado.
Cada grupo de texto de búsqueda marcado con paréntesis puede ser referenciado por un número de referencia escapado. Por ejemplo, el primer grupo de paréntesis puede ser referenciado por \1, el segundo por \2, etcetera.
En este ejemplo, cambiaremos de orden las dos primeras palabras de cada línea.
$ sed 's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/' annoying.txt is this the song that never ends yes, goes it on and on, my friend people some started singing it knowing not what it was they and'll continue singing it forever because just...
Como se puede notar, los resultados no son perfectos, la 2 y 5 línea no cumplieron con lo que se pedía, debido a la , y el ' que no están indicados en nuestro conjunto de caracteres indicados.
Antes de continuar y mejorar este último ejemplo, entendamos bien el ejemplo actual:
Recordemos que el comando s se forma de la siguiente manera:
's/buscar_un_patrón/sustituir_por_otro_patrón/'
Entonces tenemos:
's/\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)/\2 \1/'
\([a-zA-Z0-9][a-zA-Z0-9]*\) \([a-zA-Z0-9][a-zA-Z0-9]*\)
\([a-zA-Z0-9][a-zA-Z0-9]*\) = \1
\([a-zA-Z0-9][a-zA-Z0-9]*\) = \2
\2 \1
Analizemos ahora la expresión regular: \([a-zA-Z0-9][a-zA-Z0-9]*\)
\( ah ok, ahorita no puedes [a-zA-Z0-9]
Si encuentras útil la información que proveé LinuxTotal, considera realizar un donativo que estimule a seguir proporcionando contenido de calidad y utilidad. Gracias.
Dona a través de paypal::
O a través de bitcoins:
Una buena contraseña o password, todos lo sabemos, es esencial para dificultar la entrada a nuestro sistema, sobre todo si se es ....
Imaginémonos a la empresa "Pato, S.A." que ofrece a sus empleados y clientes el sitio http://www.pato.com/consulta, donde mediant....
Este es un pequeño y útil tip que te permitirá crear PDF's a partir de páginas del manual. Cuando deseas ver la ayuda de un co....
Uno de mis clientes tiene múltiples aplicaciones basadas en VisualBasic 6 y como base de datos Access, que se ejecutan directamen....
Administración básica de redes. Conoce distintos métodos y herramientas para escanear, probar o buscar por puertos abiertos des....
La gente considera encriptar algunos o todos sus archivos por múltiples razones. Ya sea que no puedan depender en seguridad físi....
Sistemas basados en GNU/Linux (Al igual que sus parientes basados en Unix como BSD o los de Macinstosh) conservan la tradición de....
Aqui, traté de enviar un archivo ejecutable (notepad.exe) a través de gmail, y sus mecanismos de seguridad me lo impidieron. Gma....
En el artículo de LinuxTotal.com.mx sobre permisos se explica lo que es un archivo con permisos SUID o SGID, pueden ser potencial....
En este archivo de configuración se indica el modo en que los mensajes del sistema son bitacorizados a través de la utileria sys....