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 ...>