如何将不以“

如何将不以“

我有一个包含 XML 行的日志。示例格式如下:

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

我想扫描日志文件并将不以“<”开头的行附加到上一行。输出如下:

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

谢谢

答案1

我想我以前已经说过这一点 - 但有听起来像卡住的记录的风险 - 不要使用正则表达式来解析 XML。它很脆并且容易破裂。但我首先会问——你为什么要做你正在做的事情?因为在使用 XML 时它应该是无关紧要的。

相反,使用解析器:

#!/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;

这可以满足您的要求...但是如果您实际上正常使用 XML,那么该trimmed_text方法可能无论如何都不需要进行此处理。

答案2

Perl 来救援!

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

即从每一行中删除换行符,并在下一行以空格开头后跟<.时打印它。

要保留最后的换行符,请更改chompchomp unless eof或添加END { print "\n" }

答案3

几乎标准的 sed 程序

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

答案4

使用 XPath 函数normalize-space删除/head/body/line节点的初始换行符:

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

或者,使用缩写名称:

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

给定问题中的输入,输出将是

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

如果您想影响输入文档中的所有节点,请使用//line代替根节点的完整路径。line

在生成的文档的开头添加-O--omit-decl之后edited丢弃声明。<?xml ...>

相关内容