Sustituir contenido de un fichero desde la terminal


cambiar contenido fichero de texto desde la línea de comandos de LinuxSuele ser habitual encontrar en las explicaciones de Internet la necesidad de sustituir algún dato en un fichero de texto obligando para ello al usuario a localizar el archivo, hacer una búsqueda en su contenido y hacer el cambio pedido sin equivocarse en ninguno de los pasos.

No es una tarea excesivamente complicada pero si que puede resultar aburrida, innecesaria y propensa a errores.

Para uno de los artículos que voy a publicar próximamente se requiere hacer una operación de este tipo y, como imagino que no será la última vez que tengamos que hacer algo así he optado por publicar este artículo en el que explico cómo realizar, con una sola instrucción, algunas operaciones básicas sobre el contenido de un fichero de texto desde la línea de comandos.

Texto de ejemplo

Sea el contenido del fichero /tmp/frases.txt, que usaremos en nuestros ejemplos, el siguiente

Francisco compra el Pan
Odio que me despierte el panadero
Compra pan cuando estés acampando
Tengo congelado algo de pan de la semana pasada

Veamos qué podemos hacer con él

Buscar y reemplazar un texto

Sustituir texto

Si lanzamos desde la terminal un

sed 's/pan/XXXX/g' /tmp/frases.txt

obtendremos como resultado

Francisco compra el Pan
Odio que me despierte el XXXXadero
Compra XXXX cuando estés acamXXXXdo
Tengo congelado algo de XXXX de la semana pasada

Ignorar mayúsculas y minúsculas

En la primera frase se nos ha escapado Pan para evitarlo debemos lanzar el comando sed del siguiente modo

sed 's/pan/XXXX/gi' /tmp/frases.txt

NOTA: Observa el /gi al final del patrón

obtendremos como resultado

Francisco compra el XXXX
Odio que me despierte el XXXXadero
Compra XXXX cuando estés acamXXXXando
Tengo congelado algo de XXXX de la semana pasada

Sustituir palabras completas

En los ejemplos anteriores encontramos que se han producido sustituciones de texto en palabras como panadero y acampando. Para evitarlo utilizaremos /b del siguiente modo

sed 's/pan\b/XXXX/gi' /tmp/frases.txt

obteniendo como resultado

Francisco compra el XXXX
Odio que me despierte el panadero
Compra XXXX cuando estés acampando
Tengo congelado algo de XXXX de la semana pasada

Líneas de inicio y fin

Si queremos que sólo se cambie el texto comprendido entre dos líneas del fichero (ambas incluidas) deberemos recurrir al siguiente comando

sed '2,3s/pan/XXXX/gi' /tmp/frases.txt

NOTA: observa el 2,3 que indica que los cambios deben realizarse en las líneas 2 y 3 dejando inalteradas el resto.

NOTA: observa igualmente que he quitado el /b para que sustituya cualquier ocurrencia de pan sin tener en cuenta si es, o no, una palabra completa o está dentro de otra; de este modo conseguimos que se vean cambios en ambas líneas.

El resultado del comando anterior sería

Francisco compra el Pan
Odio que me despierte el XXXXadero
Compra XXXX cuando estés acamXXXXdo
Tengo congelado algo de pan de la semana pasada

De una línea hasta el final

Si queremos cambiar todas las ocurrencias desde una línea concreta hasta el final, lanzaremos el comando del siguiente modo

sed '2,$ s/pan/XXXX/gi' /tmp/frases.txt

observando que se ha utilizado $ en lugar del número de línea final para indicar que debe llegar hasta el final del fichero.

El resultado sería

Francisco compra el Pan
Odio que me despierte el XXXXadero
Compra XXXX cuando estés acamXXXXdo
Tengo congelado algo de XXXX de la semana pasada

Conclusión

Espero que el «tochaco» de comandos y ejemplos os sirva de referencia y os ayude a comprender cómo realizar sustituciones en el contenido de un fichero de texto plano utilizando la línea de comandos.

Como indico mi objetivos es poder utilizarlo como referencia en otros artículos (evitando de este modo a los lectores tener que realizar tareas propensas a error) pero nadie evita que este conocimiento pueda ser aplicado igualmente a scripts en bash que simplifiquen dichos procesos.

12 comentarios en “Sustituir contenido de un fichero desde la terminal

  1. Pingback: BlogESfera.com
  2. Perdone mi indiscrección, pero llevo rato buscando por todo google una forma de usar sed que haga… por ejemplo en su frase de ejemplo , borrar todo lo que haya entre la palabra ‘que’ y ‘algo’. Primero borrando ambas incluidas, y segundo sin borrarlas.

    ¿Esos dos ejemplos, como se hacen? Espero pueda ayudarme,Gracias.

    Me gusta

  3. Gracias por contextarme.
    La verdad que jugando jugando he llegado a una solución, pero tiene un pequeño fallo, le mostrare con un ejemplo:

    La mariposa era bonita, con un ala rosa y un ala azul.

    Si por ejemplo yo quisiera borrar(o sustituir) todo lo que hay entre ‘era’ y ‘ala’… tendría problemas con el segundo ‘ala’ si escribo:

    sed ‘s/era.*ala//g’

    por que efectivamente me borra todo desde ‘era’ hasta ‘ala’ pero no el primero, si no el segundo ‘ala’, por lo que pienso que debo expecificar que quiero que sea siempre hasta el ‘primer ala’ que encuentre.

    Si se pregunta ¿para que demonios necesito hacer esto? ¿Para que me voy a comer la cabeza por algo así?

    Aquí le explico mi meta:
    Muchas veces usando Kompiz para crear webs de manera sencilla observo que en el modo wysiwyg va dotando a todas las etiquetas html de estilos css…. de manera style=»lo que sea chim pum; lo que sea mas; etc…;» cosa que no me gusta por que yo prefiero usar una hoja css a mi manera, yo quería hacer un script en bash que cogiera el archivo html que acabo de crear, y le borre toooooooodas las sentencias de estilos, y con esta sentencia sed:

    sed ‘s/style\=\».*\;\»//g’

    efectivamente encuentra muchísimos ;» finales y me borra casi todo lo que encuentra en cada linea… al igual que pasa con el problema de ‘ala’ de arriba, es muy fustrante, llevo tres días con esto… y son tantas html que quiero editar… que mejor hubiese empezado hace tres días a borrarlas una a una…

    Bueno, espero que le interese lo demasiado el asunto, como para que le pueda dedicar algún minutejo más próximamente.

    Gracias por todo.
    Markus

    Por cierto, le felicito por el blog. Me ha gustado mucho. Saludos

    Me gusta

  4. Bueno, sólo comentarle que ya lo he solucionado
    Frase:

    La mariposa era bonita, con un ala rosa y un ala azul.

    Para borrar o sustituir lo que hay entre «era» y el primer «ala» sin borrar ambas palabras:

    s/(?<=str1)(?:[^])*?(?=str2)//g

    Y para borrar o sustituir lo que hay entre "era" y el primer "ala" borrando ambas palabras inclusive:

    s/ era="[^"]*ala//g

    Por lo tanto para borrar las lineas de estilo en las tags html sería

    s/( cellspacing| bordercolor| border| style)="[^"]*"//g

    Un saludo, y gracias por todo.
    Hasta pronto.

    Me gusta

    1. Gracias a ti @Markus por tomarte la molestia de comentar la solución (tengo que probarla en cuanto encuentre un hueco).

      Estuve mirando varias soluciones pero el que sed sea «greedy» me estaba fastidiando el resultado 😦

      Enhorabuena y perdona que no haya podido dedicarle tanto tiempo como me hubiese gustado

      Me gusta

  5. Hola,

    Alguno sabe si se le puede especificar al sed que realize el cambio solo la primera o la quinta vez que lo encuentra?

    Me imagino que indicandole la linea podría funcionar, pero que pasaría si no sabes en que linea esta?

    Gracias.

    Me gusta

  6. Hola estimado, como haría para sustituir un texto especifico con espacios, puntos, igual y otros por ejemplo:
    hola.1.adios=despedida
    por el siguiente
    hola.1.adios=saludo

    El texto no siempre esta en la misma linea y es en diferentes equipos por eso no puedo hacerlo por linea el reemplazo.

    Saludos,

    Me gusta

    1. Yo optaría por utilizar expresiones regulares con la técnica descrita en el artículo.

      Para tu problema en concreto necesitaría tener más detalles:

      1. ¿Las cadenas que indicas aparecen a principio de línea?
      2. ¿Podemos tener otros contenidos detrás de la palabra «despedida»?
      3. ¿Puedo suponer que el signo de igualdad (=) es el que marca la sustitución de todo lo que hay a su derecha?

      Interesante propuesta Jorge, igual tengo que dedicarte un nuevo artículo ¿Qué os parece? 😉

      Me gusta

Deja un comentario

Este sitio utiliza Akismet para reducir el spam. Conoce cómo se procesan los datos de tus comentarios.