如何转义xml以便在perl多行搜索和替换中使用?

时间:2015-06-26 20:09:21

标签: regex xml bash perl

我想使用perl替换xml文件中的键值对,但是我遇到了从正则表达式解析器中转义xml的问题。 所有这些都应该从bash脚本运行。所以我有两个变量:

macDefault="<key>DefaultVolume</key>\
                <string>91630106-4A1F-4C58-81E9-D51877DE2EAB</string>"

winDefault="<key>DefaultVolume</key>\
                <string>EBD0A8B3-EE3D-427F-9A83-099C37A90556</string>"

我希望perl在文件config.plist中用$ winDefault的值替换$ macDefault值的出现

不幸的是

perl -0pe  's/'"$macDefault"'/'"$winDefault"'/' config.plist

不起作用,正如perl报道:

Having no space between pattern and following word is deprecated at -e line 1.
Bareword found where operator expected at -e line 1, near "s/<key>DefaultVolume</key>                <string>91630106-4A1F-4C58-81E9-D51877DE2EAB</string"
Having no space between pattern and following word is deprecated at -e line 1.
Bareword found where operator expected at -e line 1, near "<string>EBD0A8B3"
        (Missing operator before EBD0A8B3?)
Bareword found where operator expected at -e line 1, near "427F"
        (Missing operator before F?)
Bareword found where operator expected at -e line 1, near "9A83"
        (Missing operator before A83?)
Bareword found where operator expected at -e line 1, near "099C37A90556"
        (Missing operator before C37A90556?)
syntax error at -e line 1, near "s/<key>DefaultVolume</key>                <string>91630106-4A1F-4C58-81E9-D51877DE2EAB</string"
Illegal octal digit '9' at -e line 1, at end of line
Illegal octal digit '9' at -e line 1, at end of line
Execution of -e aborted due to compilation errors.

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

使用正确的XML解析器总是比尝试使用正则表达式破解某些东西

更好

以下是使用Mojo::DOM的示例,因为它常常被忽略,转而支持XML::TwigXML::LibXML

我必须将您的XML示例包装在<root>元素中,以使其格式正确。我确信真正的文档看起来不像这样,但这是我得到的最好的猜测,真实案例不太可能要求Perl被更改很多

输入文件需要作为命令行上的参数

use strict;
use warnings;

use Mojo::DOM;

my $xml = do { local $/; <> };
my $dom = Mojo::DOM->new->xml(1)->parse($xml);

my $keys   = $dom->find('key')->grep(sub { $_->text eq 'DefaultVolume' });
my $string = $keys->[0]->next;
$string->content('EBD0A8B3-EE3D-427F-9A83-099C37A90556');

print $dom, "\n";

输出

<root>
  <key>DefaultVolume</key>
  <string>EBD0A8B3-EE3D-427F-9A83-099C37A90556</string>
</root>

答案 1 :(得分:1)

我敢打赌这会奏效:

macDefault="91630106-4A1F-4C58-81E9-D51877DE2EAB"

winDefault="EBD0A8B3-EE3D-427F-9A83-099C37A90556"

perl -0pe  's/'"$macDefault"'/'"$winDefault"'/' 

或者,包含您的评论:

perl -0pe 's?(<key>DefaultVolume</key>\s*<string>)'"$macDefault"'(\s*</string>)?$1'"$winDefault"$2'?s' config.plist

注意/ s用于多行匹配。