sedを使用した属性の内容に基づいたXMLの置き換え

sedを使用した属性の内容に基づいたXMLの置き換え

パラメータに基づいてXMLタグの一部の属性コンテンツを置き換える必要があります$1

次の入力があります。

<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" enabled="true">
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" enabled="true">

testname属性が次のような場合いいえ含まれ$1、そうでなければenabled値をfalsetestname する$1)が含まれている場合はenabled値をに置き換えますtrue

メモ:この例の属性よりも多くの属性が表示されることがあります。

考えてみましたが、sed他のツールがうまくいくかもしれませんか?

答え1

まだ誰も言っていないので、そうします。 XML の解析に正規表現を使用しないでください。 XMLはコンテキスト言語ですが、正規表現はそうではありません。これは、いつか混乱して衝突が発生する可能性のある脆弱なコードを生成することを意味します。

より多くの例については、以下を参照してください。https://stackoverflow.com/questions/1732348/regex-match-open-tags-book-xhtml-self-contained-tags

パーサーを使用してください。それらはさまざまな言語で存在します。個人的に好きです。perlタスクは次のとおりです。

#!/usr/bin/env perl
use strict;
use warnings;

#parser library
use XML::Twig; 

#ingest data 
my $twig = XML::Twig -> parse (\*DATA); 

#iterate all tags <ThreadGroup>
foreach my $group  ( $twig -> get_xpath('//ThreadGroup') ) {
   #check testname regex match
   if ( $group -> att('testname') =~ /AA/ ) { 
       #set enabled
       $group -> set_att('enabled', 'true');
   }
   else {
      #set disabled
      $group -> set_att('enabled', 'false'); 
   }
}

#pretty print options vary, see man page. 
$twig -> set_pretty_print('indented_a');
$twig -> print;

__DATA__
<xml>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" enabled="true" />
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" enabled="true" />
</xml>

うん - それはい正規表現はこれを安全に実行できないため、XMLパーサーを使用する必要があります。属性の順序、改行、単項タグなど、XMLの多くの項目は意味的に同じですが、正規表現は異なります。しかし、パーサーはそれによって捕まらないでしょう。

必要に応じて、上記の内容を1行に減らすことができます。

perl -MXML::Twig -e 'XML::Twig -> new ( twig_handlers => { ThreadGroup => sub { $_ -> set_att("enabled", $_ -> att("testname") =~ /AA/ ? "true" : "false" ) } } ) -> parsefile_inplace("yourfile")'

あなたのシステム管理者チームは、これを行ったことに感謝しなければなりません(とは言えません)。どの正規表現ベースのソリューションは、ある日の明確な理由なくクラッシュする可能性があります。

最も簡単な例として、XMLは意味上次のとおりです。

<xml>
  <ThreadGroup
      enabled="true"
      guiclass="ThreadGroupGui"
      testclass="ThreadGroup"
      testname="OO CSS DPM PRI"
  />
  <ThreadGroup
      enabled="true"
      guiclass="ThreadGroupGui"
      testclass="ThreadGroup"
      testname="AA CSS DPM PRI"
  />
</xml>

または:

<xml>
  <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup"
testname="OO CSS DPM PRI"/>
  <ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGroup"
testname="AA CSS DPM PRI"/>
</xml>

または:

<xml><ThreadGroup enabled="true" guiclass="ThreadGroupGui" testclass="ThreadGrou
p" testname="OO CSS DPM PRI"/><ThreadGroup enabled="true" guiclass="ThreadGroupG
ui" testclass="ThreadGroup" testname="AA CSS DPM PRI"/></xml>

または:

<xml
><ThreadGroup
enabled="true"
guiclass="ThreadGroupGui"
testclass="ThreadGroup"
testname="OO CSS DPM PRI"
/><ThreadGroup
enabled="true"
guiclass="ThreadGroupGui"
testclass="ThreadGroup"
testname="AA CSS DPM PRI"
/></xml>

これは、属性の順序付け、可能なタグのネスト、または予期しない場所で「一致する」他の部分文字列を扱う前です。

答え2

使用XMLスター:

#!/bin/sh

xml ed -u "//ThreadGroup[. = contains(@testname, '$1')]/@enabled" -v "true"
       -u "//ThreadGroup[. = not(contains(@testname, '$1'))]/@enabled" -v "false"

XMLが有効であると仮定します。 (ルートタグを追加し、空の<SomeTag>ノードを次のように適切に区別しました。<ThreadGroup>/>enabled"hello"する何):

$ cat data.xml
<SomeTag>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" enabled="hello"/>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" enabled="hello"/>
</SomeTag>

$ sh script.sh "OO" <data.xml
<?xml version="1.0"?>
<SomeTag>
  <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="OO CSS DPM PRI" enabled="true"/>
  <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="AA CSS DPM PRI" enabled="false"/>
</SomeTag>

答え3

ロジックを正しく理解すると、このsedコマンドはvalue内で指定された$ 1引数を検索し、testnameそのenabled値を検索してfalseからtrueに置き換えます。 ()!がない場合は、enabled値をtrueからfalseに置き換えます。

sed '/ testname="[^"]*'"$1"'[^"]*"/ s/ enabled="false"/ enabled="true"/;
     / testname="[^"]*'"$1"'[^"]*"/!s/ enabled="true"/ enabled="false"/' input > output

属性名(testnameと有効)の前にスペースを追加し、文字クラスを使用して正規表現の一致を支援しようとしました[^"]

答え4

#/bin/sh

sed -r 'h
    s/.*testname="([^"]*)".*/\1/
    /\b'"$1"'\b/{ g; s/enabled="[^"]*"/enabled="true"/; b}
    g
    s/enabled="[^"]*"/enabled="false"/
' file

関連情報