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값을 false;testname 하다$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의 많은 항목은 의미상 동일하지만 정규 표현식은 다릅니다. 그러나 파서는 그것에 의해 잡히지 않을 것입니다.

원하는 경우 위의 내용을 한 줄로 줄일 수 있습니다.

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

관련 정보