Como utilizar el comando sed en la vida real ejemplos y tips – Parte 1


titulo tutorial sed


Nivel : Principiante

En esta serie de 3 partes vamos a presentar el comando sed, uno de los comandos más poderosos en Linux para manipular texto y una herramienta muy valiosa para aquellos que administran sistemas Linux.


Bienvenido SED

Normalmente un administrador de sistemas tiene que modificar archivos de configuración, tablas y otros archivos de texto repetidamente para realizar cambios y ajustes. Linux trae una gran cantidad de editores de texto tanto para la línea de comandos (emacs, vim, nano, etc) como gráfico (gedit, kate, etc), este tipo de editores son útiles cuando vamos a editar un par de textos. Pero que pasa cuando queremos modificar una gran cantidad de archivos o queremos automatizar modificaciones a través de un script, en este caso es que entra el comando sed.

La versión GNU de sed viene incluida por defecto en la gran mayoría (sino en todas) las distribuciones de GNU/Linux.

En la definición de la Free Software Fundation acerca de sed:

Sed (streams editor) no es realmente un verdadero editor o procesador de texto. En cambio es utilizado para filtrar texto, por ejemplo, toma la entrada de texto y realiza sobre ella alguna operación (o conjunto de operaciones)  y imprime el texto modificado. Sed es usado típicamente para extraer parte de un archivo usando un patron o sustituyendo múltiples ocurrencias de una cadena de texto dentro de un archivo.

Al momento de escribir este tutorial la última versión estable de GNU sed (sed de ahora en adelante) es la 4.2.1. Para ver la versión que tienes ejecuta en el terminal:

sed --version

Lo Básico de Sed

El formato básico del comando sed es:

sed opciones [script] [archivo(s)]

Características principales de sed:

  • Si no se le da ningún archivo sed toma la entrada estandar (stdin).
  • Sed filtra línea por línea, no letra por letra.
  • La salida por defecto de sed es la salida estándar (stdout).

Para los ejemplos vamos a trabajar con el siguiente texto es una cita de Carl Sagan creen un archivo llamado texto1 con el siguiente contenido

Vivimos en una sociedad profundamente

dependiente de la ciencia y la tecnología y

en la que nadie sabe nada de estos temas.

Ello constituye una fórmula segura para el desastre.

Noten que el texto tiene líneas en blanco entre cada línea de texto, no las borren ya nos encargaremos de ellas.

Las acciones principales de sed son las siguientes:

Borrar línea o conjunto de líneas

Ejecuten el siguiente comando:

sed -e '1d' texto1

Deben ver en el terminal el texto sin la primera línea, vamos a analizar un poco el comando, le dimos la opción -e que es para editar, luego colocamos   ‘1d’ que le dice a sed que tome la primera ocurrencia de línea y la borre (d=delete) y luego le pasamos el nombre del archivo texto1.  Noten que sed no modifica el archivo original como tal, simplemente nos muestra la modificación en la salida estándar (stdout), si queremos guardar la modificación en un nuevo archivo debemos redireccionar la salida lo cual lo veremos más adelante.

Ahora que pasa si queremos borrar más de una línea, pues afortunadamente sed permite que le demos rangos, si queremos borrar de la línea 2 a la línea 5 ejecutamos:

sed -e '2,5d' texto1

Este comando es muy parecido al anterior solo que en esta oportunidad le estamos dando un rango de la línea 2 a la línea 5. Noten que sed toma en cuenta las líneas en blanco también.

Utilizar Expresiones Regulares

Como casi todos los comandos en Linux sed también soporta expresiones regulares las cuales son muy útiles para filtrar patrones, al utilizar estas expresiones regulares es que podemos utilizar sed a su máximo potencial.

Vamos a ver un ejemplo y después entramos en detalle. Supongamos que queremos eliminar todas las líneas en blanco de nuestro archivo de texto1 utilizaríamos el siguiente comando:

sed -e '/^$/d' texto1

Lo único que hemos cambiado en el comando es la expresión regular /^$/ esta expresión quiere decir todas las líneas que estén en blanco. Muy útil cuando queremos ver un archivo que tiene muchas líneas en blanco y queremos compactar todo para verlo mejor.

Otro comando útil es para eliminar los comentarios que comienzan normalmente con # en los archivos de configuración para eliminarlos ejecutamos:

sed -e '/^#/d' /etc/services | less

Esto elimina todas las líneas que comienzan con #. No se preocupen por modificar el archivo como les dije anteriormente sed imprime el resultado en la salida estándar (stdout) y no en el archivo.

Vamos a dar un pequeño repaso de expresiones regulares.

Las expresiones regulares son un grupo de caractéres y reglas que sirven para filtrar patrones de letras, números, símbolos y condiciones como por ejemplo al principio de la línea o al fina, un caracter o varios, etc.

Caracteres especiales:

Caracter Descripción
^ Corresponde al inicio de la línea
$ Corresponde al final de la línea
. Filtra un sólo caracter
* Filtra cero o más caracteres
[] Filtra todo el rango dentro de los []

Para entender un poco mejor vamos a ver unos ejemplos todos estos los pueden colocar dentro de las ‘ ‘ en el comando sed para filtrar según sea el caso:

Expresión Regular Descripción
/./ Filtra cualquier línea que tenga al menos 1 caracter
/…/ Filtra cualquier línea que tenga al menos 3 caracter
/^#/ Filtra cualquier línea que comience con #
/^$/ Filtra cualquier línea en blanco
/)$/ Filtra cualquier línea que termine con ‘)’ (sin espacios)
/) *$/ Filtra cualquier línea que termine con ‘)’ seguido por cero o más espacios
/[xyz]/ Filtra cualquier linea que contenga las letras ‘x’ ‘y’ o ‘z’ en minúsculas
/^[DEF]/ Filtra cualquier línea que comience con ‘D’, ‘E’ o ‘F’


Imprimir línea o conjuntos de líneas

Hasta ahora solo hemos borrado líneas pero que tal si queremos que imprima las líneas que coinciden con nuestro filtro. Vamos a ver un ejemplo supongamos que queremos imprimir las líneas que comienzan con d y e minúsculas entonces ejecutamos lo siguiente:

sed -n -e '/^[de]/p' texto1

Tenemos dos elementos nuevos en nuestro comando, el primero es la opción -n que hace que sólo se imprima lo que coincida con nuestro filtro y hemos cambiado el comando ‘d’ por el comando ‘p’ (print) que dice que imprima el espacio del patrón.

Si ejecutan el comando anterior deberían obtener sólo dos líneas.

Más de Expresiones Regulares

Ahora vamos a hacer algo más complejo vamos a mezclar dos expresiones regulares, supongamos que de nuestro archivo texto1 queremos imprimir desde la línea que comienza con Vivimos hasta la línea que finaliza con tecnología. para esto ejecutamos:

sed -n -e '/Vivimos/,/tecnología/p' texto1

Cuando se utiliza de esta forma sed filtrará cualquier línea que comience con la primera expresión, en este caso ‘Vivimos’, hasta que consiga la siguiente expresión, en este caso ‘tecnología’, esto nos permite imprimir bloques de texto delimitados por ciertas palabras o expresiones.

Por último si para cualquiera de los comandos anteriores queremos guardar el resultado en un nuevo archivo en vez de que sólo lo imprima en pantalla debemos redireccionar la salida (>) hacia el nuevo archivo por ejemplo:

sed -n -e '/Vivimos/,/tecnología/p' texto1 > texto2

Lo que acabamos de ver es lo básico de sed aún queda mucho más por descubrir y lo veremos en la parte 2 y 3 de esta serie.

Cualquier duda o sugerencias por favor dejen su comentario

Saludos

Olivers De Abreu

Director Vensign

38 comments

  1. Buenas, espero Me pueda expresar…

    Tengo miles de archivos *.txt de msdos,
    tengo un listado en excel que tengo que agregarlo a esos archivos txt, en una linea expecifica, mi ejemplo seria agregar una linea excel a la linea 50 de cada archivo de mi archivo txt, se muy poco de linux, pero si se poner los comandos si me ayudaria 😀

    seria algo asi

    echo “linea 1 que dice blala vllbla” >> archivo01.txt
    echo “linea 2 que dice blala vllbla” >> archivo02.txt
    echo “linea 3 que dice blala vllbla” >> archivo03.txt
    echo “linea 4 que dice blala vllbla” >> archivo04.txt
    echo “linea 5 que dice blala vllbla” >> archivo05.txt
    echo “linea 6 que dice blala vllbla” >> archivo06.txt
    echo “linea 7 que dice blala vllbla” >> archivo07.txt

    disculpas por usar echo, con windows jamas he podido, ya que me los envia hasta el final, si me ayudaran a agregar esto con sed a mis archivos y en Cierta linea especifica de mis archivos txt… mil gracias por su atencion

    por mi conociemito esto lo podria poner en algun tipo bath mi linea de comando y que se ajecute cada accion.. gracias de nuevo

  2. Compruebo que el mensaje ha sido modificado. Contenía código html y ha sido suprimido. así que modifico el mensaje original:
    Me explico:
    Tengo el archivo origen.html, cuyo contenido es:
    El autor se llama Pedro Fernández y es de Madrid
    y un archivo destino.txt cuyo contenido es:
    Juan Pérez,
    Quiero copiar desde «El autor se llama» hasta «y es de Madrid» al final del archivo destino.txt, de forma que quede:
    Juan Pérez, Pedro Fernández
    Gracias adelantadas por la respuesta.

  3. Tengo una Lista de nombres.
    Como hago para Eliminar todas las lineas, menos los que a contengan un apellido en concreto.

    Ejemplo

    Pablo Diaz xxx
    Elena Lopez xxx
    Sandra Bold xxx
    Manuel Carrasco xxx
    Elena Diaz xxx
    Paco Nuñez xxx
    Picolo Diaz xxx

    tengo que imprimir en panta paco nuñez

  4. Estimado Oliviers, aqui va la primer pregunta del dia:

    Tengo un archivo con unas 20,000 lineas y quisiera conservar solo las que tienen al interior de la linea los caracteres “.” y “_”, como sería la sintaxis? aquí te envío un breve ejemplo de dicho archivo:

    TITLE= ” Monarch_dem: time 0:02:0 (hrs:min:sec), V*=0.184685″
    VARIABLES = “X”, “Y”, “PILE_HEIGHT”, “X_MOMENTUM”, “Y_MOMENTUM”, “ELEVATION” “PILE_HEIGHT_ELEV”, “CORRECTSPEED”

    ZONE N=9060, E=10108, F=FEPOINT, ET=QUADRILATERAL
    3.673997e+05 2.166358e+06 0.000000e+00 0.000000e+00 0.000000e+00 3.091975e+03 3.091975e+03 0.000000e+00

    3.674444e+05 2.167255e+06 0.000000e+00 0.000000e+00 0.000000e+00 3.255569e+03 3.255569e+03 0.000000e+00
    3.682495e+05 2.165802e+06 0.000000e+00 0.000000e+00 0.000000e+00 3.146374e+03 3.146374e+03 0.000000e+00
    3.673997e+05 2.166272e+06 0.000000e+00 0.000000e+00 0.000000e+00 3.077231e+03 3.077231e+03 0.000000e+00
    3.681153e+05 2.166785e+06 3.650801e-03 -1.672046e-02 -8.758958e-02 3.293304e+03 3.293307e+03 0.000000e+00
    9059 1 8588 260
    3011 4 216 2042
    8 5 2 1
    9060 7 8587 265
    7 9060 9056 9056

    Muchas Gracias!

    Antonio

  5. Hola necesito saber como eliminar una columna o parte de ella en un archivo que viene separado por comas

    Ej: necesito eliminar los 0009 solo de la segunda columna sin afectar a la cuarta columna

    AAAA,0009BBB,CCC,0009DDD
    AAAA,0009BBB,CCC,0009DDD
    AAAA,0009BBB,CCC,0009DDD

    Resultado esperado

    AAAA,BBB,CCC,0009DDD
    AAAA,BBB,CCC,0009DDD
    AAAA,BBB,CCC,0009DDD

  6. Hola!! ¿cómo hacéis cuando hay que sustituir algo con caracteres especiales??
    Es decir, algo así:

    sed -i ‘s/configure=/path/to/file.conf/configure=file.conf/’ fichero

    yo quiero sustituir “configure=/path/to/file.conf” por “configure=file.conf”
    pero claro, las barras lo lían todo…

    Gracias y Saludos

  7. Hola!! ¿cómo hacéis cuando hay que sustituir algo con caracteres especiales??
    Es decir, algo así:

    sed -i ‘s/configure=/configure=file.conf/’ fichero

    yo quiero sustituir “configure=” por “configure=file.conf”
    pero claro, las barras lo lían todo…

    Gracias y Saludos

  8. buenas tengo un problema, tengo una lista alumnos.txt que tiene cedula, nombre y apellido, tengo una lista notas.txt que tiene cedula, materia y nota.
    el caso es que no se como hacer para modificar una fila de alumnos.txt y tambien en notas, osea que si modificas la cedula de un alumno te modifique la cedula de notas.txt
    si hay alguien que me pueda ayudar muchisimas gracias, saludos

  9. Hola muy buenas yo quiero saber , que debo hacer en la terminal , dentro de un directorio , si por ejemplo , escribo “ls” , obtengo nombres como los siguientes

    inukaze@Inukaze:/media/stryder/Animes/Saikano$ ls
    [AnS]Saikano-Another_Love_Song_Mission_1_OVA-DVDrip(Sub_Esp-Xvid).avi [ANS].Saikano.Capítulo.09.By.deku.avi
    [AnS]Saikano-Another_Love_Song_Mission_2_OVA-DVDrip(Sub_Esp-Xvid).avi [ANS].Saikano.Capítulo.10.By.deku.avi
    [ANS].Saikano.Capítulo.01.By.deku.avi [ANS].Saikano.Capítulo.11.By.deku.avi
    [ANS].Saikano.Capítulo.02.By.deku.avi [ANS].Saikano.Capítulo.12.By.deku.avi
    [ANS].Saikano.Capítulo.03.By.deku.avi [ANS].Saikano.Capítulo.13.By.deku.avi
    [ANS].Saikano.Capítulo.04.By.deku.avi [sda]saishu.heiki.kanojo.2006.live.[subspanish].avi.0
    [ANS].Saikano.Capítulo.05.avi [sda]saishu.heiki.kanojo.2006.live.[subspanish].avi.1
    [ANS].Saikano.Capítulo.06.By.deku.avi [sda]saishu.heiki.kanojo.2006.live.[subspanish].avi.2
    [ANS].Saikano.Capítulo.07.By.deku.avi [sda]saishu.heiki.kanojo.2006.live.[subspanish].avi.3
    [ANS].Saikano.Capítulo.08.By.deku.avi

    Muy bien , quiero que todos los que dicen “í” sean renombrados por “í” sin modificar el resto del nombre , que debo usar o hacer para que esto sea correctamente renombrado de la manera que busco ???

  10. Solo como una observacion.

    Cuando los requerimientos se van volviendo mas y mas complejos, talvez sea hora de pasarse al rey de los filtros (que es el nombre generico de este tipo de programas, que toman un gran volumen de datos, los manipulan de alguna manera y entregan un nuevo flujo de datos), naturalmente me refiero al awk.

    El autor del sitio podria iniciar una nueva serie (docendo discitur), o los que consultan remitirse a algun tutorial de awk, que los hay muy buenos.

    Suerte a todos. Y al autor gracias por su tiempo y dedicacion.

    exitos!

  11. hola mirar tengo un archivo de texto el que sea ( que solo contiene texto frases).

    y necesito hacer lo siguiente (en linux):

    en el fichero completo.

    quiero que me sustituya el caracter T por P y el caracter s por a.

    Como se podria hacer esto, alguna sugerencia o ayuda.

    necesito saber el comando a aplicar y sus modificadores.

    muchas gracias

    y otro filtrado que quiero que me haga con el archivo es:

    que a partir de este fichero, me cree otro fichero, pero solo con todas aquellas
    palabras que contengan solo dos caracteres.

    COmo seria el comando y los modificadores

    gracias

  12. Hola a todos, estoy armando un script y tengo que ir guardando todo lo que se vaya haciendo en un log, no encuentro la forma de hacer que me vaya guardando cada cosa en el mismo archivo una debajo de la otra sin que lo último que guarde (con “cat” por ejemplo) me sobreescriba lo anterior. Saludos y muchas gracias a quien pueda ayudarme.

    1. César, no nos indicas como estás haciendo la redirección de la salida. Para añadir datos a un fichero, debes utilizar doble direccionador ( >> ) si lo usas simple ( > ) genera un fichero nuevo con el contenido que le envía el direccionador simple.

      Si no es esto, muestranos el código del script para poder concretar un poco más.

      Un saludo.

  13. Llevo varias horas probando con sed y no he sido capaz de conseguir añadir una cadena en un punto concreto de una línea, identificada por el comienzo de la línea

    Las líneas son de este tipo

    user1@dom.com user1
    user2@dom.com user2

    Entre ambas columnas hay un tabulador.

    El resultado que busco es que incluyendo en un script “user1” (o user1@dom.com) me modifique la linea a “user1@dom.com alias-user1”

    Gracias por adelantado
    Antonio.

  14. Holas,
    tengo el siguiente texto, disperso por todo el archivo similar a:

    xxxxxxxxx, to_date(’04-03-2005 21:50:03′, ‘dd-mm-yyyy hh24:mi:ss’), yyyyyyyyyy
    xxxxxxxxx, to_date(’09-03-2008 21:50:04′, ‘dd-mm-yyyy hh24:mi:ss’), yyyyyyyyyy
    xxxxxxxxx, to_date(’05-03-2008 21:50:29′, ‘dd-mm-yyyy hh24:mi:ss’), yyyyyyyyyy

    Pero no esta ordenado en lineas como lo estoy mostrando ok, y me debe quedar

    xxxxxxxxx,(’04-03-2005 21:50:03′), yyyyyyyyyy
    xxxxxxxxx,(’09-03-2008 21:50:04′), yyyyyyyyyy
    xxxxxxxxx,(’05-03-2008 21:50:29′), yyyyyyyyyy

    Aún no encuntro la forma de representar los caracteres especiales y el espacio.

  15. Si tengo la siguiente lista:

    abcd00001 ddddd 72869 ffffff
    efgh00002 ddddd 72870 ffffff
    ijkl00003 ddddd 72871 ffffff
    mnop00004 ddddd 72872 ffffff

    Cómo podría hacer para que los valores de las columnas 19 a 23 (inclusive) se copien al inicio de cada línea? Este sería el resultado que espero:

    72869abcd00001 ddddd 72869 ffffff
    72870efgh00002 ddddd 72870 ffffff
    72871ijkl00003 ddddd 72871 ffffff
    72872mnop00004 ddddd 72872 ffffff

    Espero que me puedan ayudar. Gracias.

    1. Quiero borrar una columna en blanco tengo este archivo
      904243381 CM10 12.04.2010 OBSERVACION DE TAREAS
      SEGURIDA CIVIL ABIE DMNV EDET KKMP PREC 904243382 CM10 12.04.2010 EQUIPO DE PROTECCION PER
      SONAL SEGURIDA CIVIL ABIE DMNV EDET KKMP PREC
      Quiero borrar el espacio que existe ente 904243380 CM10, este archivo lo estoy preparando para subirlo a una tabla, me esta causando error por que me pone una Columna de mas.
      Gracias Olivers….

  16. Yo tambien Tengo una Lista de nombres.
    Como hago para Eliminar todas las lineas, menos los que a contengan un apellido en concreto.
    Ejemplo
    Pablo Diaz xxx
    Elena Lopez xxx
    Sandra Bold xxx
    Manuel Carrasco xxx
    Elena Diaz xxx
    Paco Nuñez xxx
    Picolo Diaz xxx
    Quiero Eliminar todos los que no Tengan apellido Diaz y lopez

  17. Eres un Genio Olivers

    Muchas Gracias, ha sido rápido, muy útil sencillo, y exacto.

    Yo tenia Grandes lineas. Muchas Gracias por su respuesta.
    Sera de utilidad para mas persona.

    Visto el blog, lo completo y profesional
    os recomendare a todos mis conocidos.
    un saludo.

  18. Hola Sonia sería así:

    sed ‘/Diaz/!d’ nombres.txt

    Siendo nombre.txt el archivo donde tienes la lista de nombres. Recuerda que sed no modifica y tendrías que guardarlo en otro archivo de la siguiente forma:

    sed ‘/Diaz/!d’ nombres.txt >> solodiaz.txt

    Espero que te sirva

    Saludos
    Olivers

  19. Tengo una Lista de nombres.
    Como hago para Eliminar todas las lineas, menos los que a contengan un apellido en concreto.

    Ejemplo

    Pablo Diaz xxx
    Elena Lopez xxx
    Sandra Bold xxx
    Manuel Carrasco xxx
    Elena Diaz xxx
    Paco Nuñez xxx
    Picolo Diaz xxx

    Quiero Eliminar todos los que no Tengan apellido Diaz

  20. Hola Laura… mira ya lo tengo eso que querias hacer con tu texto de aaa,… blah blah blah jajaj…. lo unico que tienes que hacer es ir reduciendo por parte cada linea o cambiando cadenas de caracteres por un valor nulo.

    El codigo queda asi:

    sed “s/ddd//g” textoprueba.txt | sed “s/fff//g” | sed “s/ggg//g” | sed “s/ / /g”

    Lo que hacemos es que en el primer sed.. cambiamos la cadena ddd por un valor nulo.
    En la siguiente cadena sed hacemos lo mismo con f despues con g y al final cambiamos los 3 espacios por uno solo, cuando busque al final del archivo la cadena que tiene 3 espacios, al localizarla la cambiara por una que sea de 1 solo espacio…

    Espero aun te sirva esta informacion.. y que hayas solucionado tu problema. aunque aun existen muchas formas para llegar a la solucion pero siento que esta es la más facil de interpretar. Nos vemos y que estes bien..

  21. saludos, señores tengo un script y no lo corro porque no se que significa , asi que si pueden ayudenme por favor.
    ((((el fin de este es cambiar la mac addres a un router que opera con un sistma basado en linux , y lo admite))))

    echo “sed -i -e ‘s#/sbin/wlanconfig “ath0”
    create#ifconfig wifi0 hw ether XX:XX:XX:XX:XX:XX;
    /sbin/wlanconfig “ath0″ create#’ /etc/sysinit/radio.conf” > /etc/persistent/rc.prestart
    cfgmtd -w -p /etc/
    reboot

    la parte que quiero saber que significa es : sed -i -e

    gracias.