1

この XML データを含むファイルがあります。

<?xml version="1.0" encoding="utf-8"?>
<root>
  <item>
    <tag1>some text</tag1>
    <tag2><![CDATA[http://url1.com]]></tag2>
    <tag3 />
    <tag4>not empty node</tag4>
  </item>
  <item>
    <tag1>some other text</tag1>
    <tag2><![CDATA[http://www.url.com]]></tag2>
    <tag3 />
    <tag4 />
  </item>
</root>

(そして内部にはさらに多くのXMLがあります)

XML の一部を削除する Bash スクリプトを作成しようとしています。つまり、空の子要素<item>を持つすべての要素を削除したいと考えています。<tag4>

<item>したがって、検索してから<tag4/>検索し、これをグループ化し、文字</item>に置き換えたいと考えています。X

私はまだグループ化さえしていません。複数の行で正規表現を行うことに行き詰まっています。

Mac OSX での実行

これは私が持っているものです:

 perl -pn -e "s/<item>[\s\S]*<tag4 \/>/X/g" $XML_FILENAME > new_folder/$XML_FILENAME

[\s\S]*(つまり、スペース文字または任意の文字を削除すると、<item>タグを置き換えることができますが、次のタグまたは次の行に移動できません。

(私も同様の位置で立ち往生しようecho//としました)sed

4

5 に答える 5

2

これを試して:

s/<item>(?>[^<]++|<(?!tag4))*<tag4 \/>(?>[^<]++|<(?!\/item>))*<\/item>/X/g

このパターンは、ドットを使用しないため、改行の問題を回避します。

説明

の詳細(?>[^<]++|<(?!tag4))*

(?>                # open an atomic group
      [^<]++       # all that is not a < one or more times (possessive)
    |              # OR
      <(?!tag4)    # a < not followed by tag4
)*                 # close the atomic group, repeat zero or more times

<tag4このトリックを使用すると、次のものが(または文字列の最後)であることを確信しています

より多くのパフォーマンスのために原子群 (?>..)所有量指定子 を使用しますが、通常のグループと貪欲な量指定子++に置き換えることができます(?:..)+

特記事項

または、遅延量指定子を使用して[\s\S]*[\s\S]*?

perl では[\s\S]、s 修飾子を追加する代わりに dotall モードを使用できることに注意してください。

 (?s).*          # the dot matches newlines
 (?-s).*         # the dot doesn't match newlines (default behavior)
于 2013-06-26T15:33:27.757 に答える
2

正規表現を使用して XML を処理することは実用的ではありません。適切な Perl モジュールを使用する必要があります。

この短いプログラムはXML::Twig、コマンドライン パラメータとして渡された名前のファイルを処理するために使用します。変更された XML を に送信しますSTDOUT

use utf8;
use strict;
use warnings;

use XML::Twig;

my $twig= XML::Twig->new(pretty_print => 'indented');
$twig->parsefile($ARGV[0]);

for my $twig ($twig->findnodes('/root/item')) {
  $twig->delete unless $twig->findvalue('tag4') =~ /\S/;
}

$twig->print;

出力

<?xml version="1.0" encoding="utf-8"?>
<root>
  <item>
    <tag1>some text</tag1>
    <tag2><![CDATA[http://url1.com]]></tag2>
    <tag3/>
    <tag4>not empty node</tag4>
  </item>
</root>
于 2013-06-26T15:53:43.987 に答える
0

これは機能しますが、少し作業が必要です:

 perl -00 -ne 's/<item>.*<\/tag4>.*<\/item>/X/gs;print "$_\n";' test.xml 
于 2013-06-26T16:52:18.197 に答える