줄을 변경하고 전체 태그를 제거해야 하는 XML 파일이 있으므로 (client_23.xml)
Perl 스크립트를 생각해 냈습니다.
내 XML 파일에는 이와 같은 블록이 있습니다. <hello>collect_model = 1</hello>
내 XML 파일에는 인스턴스가 하나만 있습니다.
<world>
<hello>collect_model = 1</hello>
<hello>enable_data = 0</hello>
<hello>session_ms = 2*60*1000</hello>
<hello>max_collect = string_integer($extract("max_collect"))</hello>
<hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello>
<hello>output('{')</hello>
</world>
해당 줄을 다음과 같이 변경해야 합니다. <hello>collect_model = 0</hello>
따라서 전체 블록을 변경한 후 다음과 같아야 합니다.
<world>
<hello>collect_model = 0</hello>
<hello>enable_data = 0</hello>
<hello>session_ms = 2*60*1000</hello>
<hello>max_collect = string_integer($extract("max_collect"))</hello>
<hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello>
<hello>output('{')</hello>
</world>
두 번째는 동일한 XML 파일에서 전체 태그를 제거해야 한다는 것입니다.
<derta-config>
<data-users>2000</data-users>
<test-users>2000</test-users>
<attributes>hello world</attributes>
<client-types>Client1</model-types>
<target>price.world</target>
</derta-config>
그래서 Perl을 사용하는 다음 쉘 스크립트가 있고 파일의 일부 내용을 바꾸는 동안 위의 두 가지 작업을 수행하려고 시도하지만(저는 다른 목적으로 이 작업을 수행합니다) 위의 두 가지 작업을 위해 특별히 추가한 섹션에서는 그렇지 않았습니다. 작업을 하고 많은 오류를 인쇄하기 시작했습니다.
perl -0pe "s#<eval>collect_model = 0</eval>#<eval>collect_model = 1</eval> s#<derta-config>.* </derta-config>##sm; s#<function>\s*<name>DUMMY_FUNCTION.+?</function>#$file#sm" client_"$client_id".xml > "$word"_new_file.xml
그래서 나는 쉘 스크립트에서 이 작업을 수행할 수 있는지 궁금했습니다. 즉, 쉘 스크립트를 사용하여 위의 두 가지를 제거한 다음 그 출력을 세 번째 단계에서 작동하는 Perl 스크립트에 전달한다는 의미입니다. 그러면 쉘 스크립트의 출력을 아래의 Perl 스크립트에 전달할 수 있습니까? 그러면 위의 두 가지가 제거됩니다. 괜찮나요?
perl -0pe "s#<function>\s*<name>DUMMY_FUNCTION.+?</function>#$file#sm" client_"$client_id".xml > "$word"_dyn_model.xml
여기도 마찬가지 $client_id
입니다 23
.$word
abc
나는 이것이 효과가 있기를 원하며 가장 쉬운 것은 무엇이든 나에게 효과가 있을 것입니다. 위에서 언급한 두 가지 사항에 대한 예를 들어 보겠습니다.
답변1
XML을 구문 분석하는 데 정규식을 사용하지 마십시오. 이것은 나쁜 생각입니다. 이것이 나쁜 생각인 주된 이유는 많은 종류의 XML이 있고 의미상 동일한 일부 XML이 상당히 다른 패턴 일치를 가질 수 있다는 것입니다.
개행, 공백, 단항 태그 등을 고려하세요.
<element />
<element></element>
둘 다 동일합니다. 그런 다음 들여쓰기, 줄 바꿈, 태그 분할 등을 수행할 수 있습니다.
<element
att1="fish"
att2="carrot">
또한 유효합니다.
그럼 나도 그럴게강하게"파서 사용"을 권장합니다. Perl에는 다양한 옵션이 있습니다. 제가 좋아하는 것은 다음과 같습니다 XML::Twig
.
#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
my $twig = XML::Twig->new( 'pretty_print' => 'indented_a' )->parse( \*DATA );
foreach my $hello ( $twig->findnodes('//hello') ) {
if ( $hello->trimmed_text =~ m/collect_model/ ) {
$hello->set_text('collect_model = 0');
}
}
$_->delete for $twig->findnodes('//derta-config');
$twig->print;
__DATA__
<root>
<world>
<hello>collect_model = 1</hello>
<hello>enable_data = 0</hello>
<hello>session_ms = 2*60*1000</hello>
<hello>max_collect = string_integer($extract("max_collect"))</hello>
<hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello>
<hello>output('{')</hello>
</world>
<derta-config>
<data-users>2000</data-users>
<test-users>2000</test-users>
<attributes>hello world</attributes>
<client-types>Client1</client-types>
<target>price.world</target>
</derta-config>
</root>
왜냐하면 당신은 Perl에서 다음 줄을 좋아하는 것 같기 때문입니다:
perl -MXML::Twig -0777 -e 'my $twig = XML::Twig->parse (<>); $_->set_text("collect_model = 0") for grep { $_->text =~ m/collect_model/ } $twig->findnodes("//hello"); $_->delete for $twig->findnodes("//derta-config"); $twig -> print;'
답변2
다음을 예제 입력 파일로 사용하십시오.
$ cat client_23.xml
<world>
<hello>collect_model = 1</hello>
<hello>enable_data = 0</hello>
<hello>session_ms = 2*60*1000</hello>
<hello>max_collect = string_integer($extract("max_collect"))</hello>
<hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello>
<hello>output('{')</hello>
</world>
<derta-config>
<data-users>2000</data-users>
<test-users>2000</test-users>
<attributes>hello world</attributes>
<client-types>Client1</model-types>
<target>price.world</target>
</derta-config>
다음을 사용하여 두 가지 변경을 수행할 수 있습니다.
$ sed 's|<hello>collect_model = 1</hello>|<hello>collect_model = 0</hello>|; \|<derta-config>|,\|</derta-config>|d' client_23.xml
<world>
<hello>collect_model = 0</hello>
<hello>enable_data = 0</hello>
<hello>session_ms = 2*60*1000</hello>
<hello>max_collect = string_integer($extract("max_collect"))</hello>
<hello>max_collect = parenting(max_collect, max_collect, 1.0e99)</hello>
<hello>output('{')</hello>
</world>
어떻게 작동하나요?
두 개의 sed 명령이 있습니다. 첫 번째는 교체이고, 두 번째는 삭제입니다.
s|<hello>collect_model = 1</hello>|<hello>collect_model = 0</hello>|
대체 명령의 형식은 입니다
s|old|new|
. 따라서 이것이old
원본<hello>collect_model = 1</hello>
이고new
이것이 대체입니다<hello>collect_model = 0</hello>
.\|<derta-config>|,\|</derta-config>|d
이는 일련의 행을 정의합니다. 시작 줄에는 가 포함되고
derta-config>
, 끝 줄에는 가 포함됩니다</derta-config>
. 이 범위 내의 모든 행은 삭제 명령에 의해 삭제됩니다d
.