Cómo ejecutar un command solo si sed reemplaza cadenas

Quiero habilitar el repository multiverso en Ubuntu mediante una línea de command.

sed -i "/^# deb.*multiverse/ s/^# //" /etc/apt/sources.list && apt-get update 

Este command ejecutará apt-get update todo el time, pero solo es necesario cuando sed comenta la línea.

¿Hay una manera fácil de detectar si sed reemplaza cadenas y ejecuta un command dependiendo de ese resultado?

Solutions Collecting From Web of "Cómo ejecutar un command solo si sed reemplaza cadenas"

Probablemente, lo más fácil de hacer aquí es simplemente grep para la línea comentada primero:

 grep -q '^# deb.*multiverse' /etc/apt/sources.list && sed -i '/^# deb.*multiverse/ s/^# //' /etc/apt/sources.list && apt-get update 

Sé que esta pregunta ya tiene una respuesta, pero tenía curiosidad por ver si podía encontrar una respuesta solo sed (sin usar grep como en la respuesta aceptada). Como resultado, parece posible:

 sed -ni '/^# deb.*multiverse/{;h;s/^# //;};p;${;g;/^#/!q1;}' /etc/apt/sources.list && apt-get update 

(Por supuesto, todo debe estar en la misma línea, pero quería que todo fuera visible sin tener que desplazarse horizontalmente).

Explicación

  • Busque el patrón ( /^# deb.*multiverse/ )
  • Si se encuentra :
    • Mantenga la línea en el búfer de retención ( h )
    • Hacer el comentario ( s/^# // )
  • Imprimir la línea
  • En la última línea solamente ( $ )
    • Copie la línea contenida en el búfer de retención en el búfer de patrones ( g )
    • Pruebe si el almacenamiento intermedio de retención comienza con un signo de comentario (estaría vacío si no ocurriera ningún reemploop) ( /^#/ )
    • Si no tenemos una coincidencia, salga con el código 1 para indicar que no se ha realizado ningún reemploop ( !q1 ) (de lo contrario, sale normalmente con el código 0 )

Ahora sé que esta respuesta no es tan clara como usar grep, pero estaba interesado en el desafío y se me ocurrió esto, así que pensé en compartirlo.

 { sed -i '/^# \(deb.*multiv.*\)/h;s//\1/p $x;s//apt-get update/w /dev/fd/2' file } 2>&1 >/dev/null | sh -v 

Ese command solo emitirá la línea apt-get update alimentada por sh sobre un conducto si hace al less un reemploop mientras lee el file .

sed no tiene variables. Existe el command t que salta a una label después de una s/// exitosa, y el command q toma un código de salida. Pero como está reescribiendo el file, no puede salir después de la sustitución, primero debe leer todo el file.

Cambiaría a otro idioma. perl funciona aquí: nuevas líneas para la legibilidad

 perl -i -pe ' BEGIN {$x=1} if (/^# deb.*multiverse/) {s/^# //; $x=0} END {exit $x} ' /etc/apt/sources.list && apt-get update 

Otra forma de hacerlo es con ed , aprovechando una function incorporada: si no se realiza ninguna sustitución en las líneas direccionadas, se considera un error; si la input estándar es un file regular, ed terminará con un estado de salida distinto de cero .
Puedes usar herestring :

 ed -s /etc/apt/sources.list <<< $',s/^# \\(deb.*multiverse\\)/\\1/\nw\n!apt-get update\nq' 

o henetworkingoc :

 ed -s /etc/apt/sources.list <<IN ,s/^# \(deb.*multiverse\)/\1/ w !apt-get update q IN 

pasar los siguientes commands a ed :

 ,s/^# \(deb.*multiverse\)/\1/ replace pattern with something w write changes to file !apt-get update run this command in shell q quit editor 

Sin embargo, si no se encuentra ninguna coincidencia, eso significa que no se realiza ninguna sustitución, por lo que ed bombardea (el único resultado es un signo de interrogación, es decir, el error 1 ) y, como resultado, los subcommands de las líneas subsiguientes no se ejecutan. Para probarlo, puedes replace la apt-get update con otro command como cat /etc/apt/sources.list o echo DONE .


1: Si el signo de interrogación le molesta, simplemente networkingireccione stderr a /dev/null por ejemplo:

 ed -s /etc/apt/sources.list 2>/dev/null <<....