'

'

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

つまり、改行は各行から削除され、次の行が空白で始まり、その後に が続く場合に出力されます<

最後の改行を残すには、chomp次のように変更するchomp 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 ...>

関連情報