¿Cómo reemplazar el contenido entre dos patrones del archivo?

9

Tengo el siguiente formato del archivo:

<common>
fitnes=0
genetic=1
method=0
</common>
<inputs>
foo=bar
bar=foo
</inputs>
<limits>
balance=200.00
</limits>

y me gustaría eliminar todo lo que está entre <inputs>y </inputs>(excluyendo el patrón por sí mismo) y reemplazarlo con el contenido de otro archivo (por ejemplo foo.txt). En otras palabras, las líneas con foo=bary bar=fooserían reemplazadas por otro contenido.

Probablemente puede ser similar a cómo elimina una coincidencia de varias líneas , como:

:g/<inputs/,/inputs>/d

pero no estoy seguro de qué debo reemplazar dpara insertar el contenido de otro archivo, pero quiero mantener el patrón coincidente.

Un enfoque similar sería eliminar el contenido interno de la etiqueta html , como

:/<inputs>/norm vitd

pero entonces no sé cómo agregarías el contenido del archivo.

Idealmente, estoy tratando de encontrar un revestimiento, ya que será parte de otro script.

¿Cómo puedo lograr eso?

kenorb
fuente

Respuestas:

10

Se puede usar una sustitución para reemplazar un patrón con el resultado de una expresión como esta:

:keeppatterns %s;<inputs>\zs\_.\{-}\ze</inputs>;\=insert(readfile('test.txt'), '')

Ver :help sub-replace-expression

Tenga en cuenta que keeppatternsevita que el substitutecomando agregue algo al historial de búsqueda y conserva el "último registro de patrón de búsqueda" - vea :help "/. Es una buena práctica para evitar que las secuencias de comandos de modificación innecesariamente el estado global de Vim con los modificadores de comando keepalt, keepjumps, lockmarks, keepmarks, y keeppatterns.

djjcast
fuente
5

Un enfoque alternativo de Gary es el siguiente:

:g/^<inputs>/+,/^<\/inputs>/-d|-r dummy

Que primero elimina todo en el patrón dado, que usa el :rcomando para leer los datos del archivo ficticio. Ahora, si necesita extraer el nombre de archivo de las líneas entre el <input>/</input>patrón, se vuelve un poco más complicado.

Christian Brabandt
fuente
4

Esto parece funcionar, al menos en un sistema Unix:

:/<inputs>/+1,/<\/inputs>/-1!cat foo.txt

Utiliza el {range}!{filter}comando para filtrar las líneas de una después <inputs>a otra antes a </inputs>través del programa externo cat foo.txt. En este caso, catignora su entrada estándar, por lo que las líneas originales se eliminan y se reemplazan por el contenido del archivo foo.txt.

Ver:

:help :range!
:help cmdline-ranges
garyjohn
fuente
2

Siento que una macro será un enfoque más fácil. Especialmente, si tienes varios lugares para hacer lo mismo.

  1. Mantenga solo esos 2 archivos abiertos.
  2. Ahora, en el primer archivo, comience a grabar por qa,( aes el nombre del registro).
  3. Busque el patrón de inicio, presione hacia abajo , luego presione Ctrl- v, busque el patrón de finalización, presione hacia arriba . Ahora se selecciona la parte que desea eliminar. Bórralo.
  4. Marque la posición usando ma( aes el nombre de la marca) y guarde el archivo.
  5. Vaya al segundo archivo, por :b2comando y, de manera similar, seleccione la parte según sus criterios de inicio / finalización.
  6. Regrese a este archivo presione apara ir a ese punto. Pegar allí por p.
  7. Busque los criterios finales nuevamente y cruce la sección para no volver a presionarlos.
  8. Salga de la grabación presionando q.
  9. Repita el número de veces por 40@a.
Krishanu Banerjee
fuente
1
Gracias por la sugerencia, está bien, pero no ayudará en este caso particular, ya que estoy buscando una solución no interactiva como parte del exscript donde puedo especificar qué archivo insertar según los argumentos de entrada del usuario.
kenorb
1

Si este es otro intento de analizar XML con herramientas que no son XML, no lo haga.

Las soluciones aquí son válidas, pero la intención podría no serlo. Si el XML no proviene de una fuente bien domesticada, ¡podría obtener escapes, CDATA o espacios en blanco en la etiqueta!

Entonces xsltproc del comando en vi puede lidiar con eso.

Matthias Š
fuente
El archivo no es en realidad un formato apropiado XML, pero en realidad no está bien documentado iniarchivo de tener esos 3-XML como las etiquetas.
kenorb