Busque y reemplace texto en un archivo solo después de que coincidan 2 patrones diferentes usando `sed` o `awk`

Busque y reemplace texto en un archivo solo después de que coincidan 2 patrones diferentes usando `sed` o `awk`

Esta es una extensión de la pregunta formulada y respondida aquí:Busque y reemplace texto en un archivo después de que coincida el patrón solo para la primera aparición usando sed

El problema es: necesito realizar una búsqueda y reemplazo, perosolodespués de la primera aparición de pattern1seguido de pattern2. Ahí es donde pattern3debe ocurrir la búsqueda y el reemplazo.

Usando una variación del archivo de muestra de la pregunta vinculada:

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '1234'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

Necesito este:

Server 'Test AB'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test AB'
    option type 'sb'
    option port '9876'
    option timeout '60'

Server 'Test EF'
    option type 'sa'
    option port '1234'
    option timeout '60'

Server 'Test GH'
    option type 'sa'
    option port '1234'
    option timeout '60'

Los dos primeros Servernombres son iguales. El option typees diferente para cada servidor. Necesito hacer coincidir un Servernombre específico ( Test AB), luego un option type( sb), y luego cambiar el número de puerto.

No sé cómo hacer que varios patrones se concatenen de forma lógica AND.

¿Algun consejo? sedo awkse prefieren soluciones (pero para los barbudos incondicionales que buscan unarealdesafío, intente hacerlo con sustitución BASH pura. BASH 5 en adelante está bien). Gracias.

Respuesta1

sedle permite especificar rangos de direcciones en un formulario addr1,addr2. La respuesta vinculada utiliza un rango. Ahora necesitas anidar rangos.

sed "
/^Server 'Test AB'$/,/^$/ {
/option type 'sb'/,/option port '/ s/option port '.*'/option port '2222'/
}" file

Significa: desde (e incluyendo) una línea hasta Server 'Test AB'(e incluyendo) la siguiente línea vacía, aplique el código dentro {}.

Y el código interior {}significa: desde (e incluyendo) una línea que contiene option type 'sb'hasta (e incluyendo) una línea que contiene option port 'aplicar el s/…/…/comando.

Y el s/…/…/comando significa: en cada línea reemplace la primera aparición de option port '.*'(donde .*coincide con avidez cero o más caracteres) con option port '2222'.

Notas:

  • Es una suerte que haya líneas vacías que podamos usar para finalizar un rango. Sin ellos estaríamos tentados a especificar rangos desde Serverhasta Server. El problema es que el primer rango desde Server 'Test AB'hasta la siguiente aparición de Serverincluiría la segunda aparición de Server 'Test AB'; y en sedlos rangos detectados por el mismo addr1,addr2código no se pueden superponer. De hecho, la segunda aparición de Server 'Test AB'no se trataría como el comienzo de un nuevo rango, por lo que el código contenido {}no se ejecutaría para las líneas de esta sección.

  • ^y $son anclas para el principio y el final de la línea respectivamente. Los usé Server 'Test AB'pero deliberadamente no los usé option type 'sb'. Ajusta el código a tus necesidades.

  • Usé comillas dobles porque los datos contienen comillas simples. Por lo general, es necesario escapar $entre comillas dobles, pero aquí tenemos /justo después de cada $; $/no es un nombre válido para una variable del shell ni nada que el shell quiera expandir, por lo que no es necesario escapar $.

información relacionada