
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
後に または を追加します。edit
ed
<?xml ...>