
我有一個包含 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 ...>