Cómo agregar una línea que no comienza con '

Cómo agregar una línea que no comienza con '

Tengo un registro que contiene líneas XML. Formato de muestra a continuación:

<head>
    <body>
        <line>
asdasd</line>
    </body>
</head>

Quiero escanear el archivo de registro y agregar las líneas que no comienzan con '<' a la línea anterior. La salida sería como a continuación:

<head>
    <body>
        <line>asdasd</line>
    </body>
</head>

Gracias

Respuesta1

Creo que ya he dicho esto antes, pero a riesgo de sonar como un disco atascado: NO uses expresiones regulares para analizar XML. Es frágil y propenso a romperse. Sin embargo, primero preguntaría: ¿por qué intentas hacer lo que estás haciendo? Porque debería ser irrelevante cuando trabaje con su XML.

En su lugar utilice un analizador:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->parsefile('your_file.xml');

foreach my $elt ( $twig->get_xpath('//#PCDATA') ) {
    $elt->set_text( $elt->trimmed_text );
}

$twig->set_pretty_print('indented_a');
$twig->print;

Esto hace lo que desea... pero si realmente está trabajando con XML normalmente, ese trimmed_textmétodo probablemente elimina la necesidad de este procesamiento de todos modos.

Respuesta2

Perl al rescate!

perl -pe 'print "\n" if /^\s*+</; chomp;' input > output

es decir, la nueva línea se elimina de cada línea y se imprime cuando la siguiente línea comienza con un espacio en blanco seguido de un <.

Para mantener la nueva línea final, cambie chompo chomp unless eofagregueEND { print "\n" }

Respuesta3

Procedimiento sed casi estándar

sed '$!N;s/\n\(\s*[^<[:blank:]]\)/\1/;P;D' log.xml

Respuesta4

Usando la función XPath normalize-spacepara eliminar la nueva línea inicial del /head/body/linenodo:

xmlstarlet edit --update '/head/body/line' --expr 'normalize-space(text())' file.xml

O, usando nombres abreviados:

xmlstarlet ed -u '/head/body/line' -x 'normalize-space(text())' file.xml

El resultado, dada la entrada en la pregunta, sería

<?xml version="1.0"?>
<head>
  <body>
    <line>asdasd</line>
  </body>
</head>

Úselo //lineen lugar de la ruta completa desde el nodo raíz si desea afectar a todos linelos nodos en su documento de entrada.

Añadir -Oo --omit-decldespués edito eddescartar la <?xml ...>declaración al inicio del documento resultante.

información relacionada