Haga coincidir un patrón y reemplace la primera instancia de cadena que lo sigue

Estoy escribiendo la modificación de un file de configuration como este:

[purple] auth = no enabled = 0 username = password = priority = 0 host = True [shovel] group = manual = False enabled = 0 username = 

Donde hay muchas [categorías] y a veces con la misma key de un par key / valor.

¿Es posible crear un trazador de líneas usando awk / sed / grep / tr / cut / perl que puede cambiar el valor de "enabled = 0" a "enabled = 1" pero SOLO para la categoría [pala]?

En sed puede usar un range (deteniéndose en la línea vacía al final de la categoría [shovel] ):

 sed '/\[shovel\]/,/^$/ s/enabled = 0/enabled = 1/' file 

la primera parte /\[shovel\]/,/^$/ significa encontrar una línea con [shovel] , sigue hasta que encuentres una línea vacía, y haz los siguientes commands (en este caso un s/old/new simple s/old/new ) solo en esa parte del file

Nota en respuesta al comentario: hasta donde yo sé, sed no aceptará delimitadores alternativos en ranges y direcciones (así que escapa de cualquiera / caracteres que deben ser literales, si necesitas hacer coincidirlos), pero aún puedes usar uno en cualquier seguimiento commands, por ejemplo:

 sed '/\[shovel\]/,/^$/ s|enabled = 0|enabled = 1|' file 

Aquí hay una solución que usa Perl, suponiendo que su configuration está en config.ini :

 perl -000 -n -i -e 's/^enabled = 0$/enabled = 1/m if /^\[shovel\]\n/; print;' config.ini 

Esto hace lo siguiente:

  • -000 – Leer el file en el modo párrafo, esencialmente lo mismo que hacer $/ = "\n\n"; en el código.
  • -n : ejecuta el código especificado dentro de un ciclo while (<>) { } .
  • -i : en línea, edite el file especificado en lugar de imprimir en la salida estándar. Opcionalmente, puede especificar una extensión, lo que hará que el file de input se respalde con esa extensión. Por ejemplo, -i.bak crearía un file de respaldo llamado config.ini.bak .
  • -e – Ejecuta el código de perl especificado.

El código en sí dice replace las líneas que contienen exactamente enabled = 0 con enabled = 1 si el "párrafo" de input comienza con [shovel] en una línea por sí mismo. Los [ y ] tienen que escaping, ya que normalmente tienen un significado especial en una expresión regular.

puedes probar esta solución awk

 awk '/shovel/{flag=1}flag&&/enabled/{$NF=1;flag=0}1' input 

Puede restringir sed a solo modificar una línea en particular:

  sed -i '3s/enabled = 0/enabled = 1/g' file 

Esto solo modificará la tercera línea para [púrpura]