매개변수를 기반으로 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