我正在处理XML文档,我需要打开它并在同一行上转换为大写某些特定标记值。如果我有相同的单词,它只替换其中一个,虽然我使用两个不同的if循环: 这是我的XML:
<pageID="1" width="827" height="1169" Sender_Company="société" Sender_Address="société" Sender_Fax="" Category="C2" Language_2="" Document_Object="" Language_1="french" Language_3="" NumPage="1" Script_1="typed">
这是我的代码:
while (<FILEIN>) {
if ($_ =~ /pageID="1"/) {
$haschanged = 1;
if ($_ !~ /Sender_Address=""/) {
if ($_ =~ /(Sender_Address="(.*?)")/){
my $SenderAddress = $2;
$SenderAddress = uc($SenderAddress);
$_ =~ s/$1/Sender_Address="$SenderAddress"/;
}
}
if ($_ !~ /Sender_Company=""/) {
if ($_ =~ /(Sender_Company="(.*?)")/) {
my $SenderCompany = $2;
$SenderCompany = uc($SenderCompany);
$_ =~ s/$1/Sender_Company="$SenderCompany"/;
#print "$_\n";
}
}
}
}
当我为Sender_Company="bla"
和Sender_Address="société"
使用两个不同的值时,转换为大写有效,但在本案例中我使用相同的单词Sender_Company="société"
和Sender_Address="société"
时它不会转换为大写。
有没有人有任何想法?当我一次使用两个不同的if循环时,我找不到它背后的逻辑,不想变换同一个单词。谢谢!
答案 0 :(得分:2)
您对XML的理解有点值得商榷:
<pageID="1">
那样加倍,没有<?xml ...?>
声明,没有根元素,...)除此之外,代码应该可以正常工作。请注意,您可以简化生活,缩短代码:
$_ =~ /foo/
与/foo/
相同,$_ !~ /foo/
与!/foo/
相同。您只需一步即可完成所有操作,而不是提取两个捕获,并将结果替换为第二个正则表达式:
s{ (?<=Sender_Address=") ([^"]+) (?=") }{ uc $1 }ex
等等,什么?我提取了一个或多个非“ - 字符,前面跟着字符串Sender_Address="
,然后是"
(环顾四周的断言)。我捕获之间的东西,用大写字母替换它因为我匹配至少一个字符,所以我不必测试空标签的情况。/e
标志允许替换中的代码(这里不是必需的),而/x
允许我们要包含不匹配的空格以便更好地格式化。
您可以为想要大写的两个属性轻松扩展它:
# This subsumes your whole logic inside `if (/pageID="1"/)`
$haschanged = 1;
for my $attr (qw/Sender_Address Sender_Company/) {
s{ (?<=\Q$attr\E=") ([^"]+) (?=") }{ uc $1 }ex;
}
\Q...\E
导致插值的东西按字面意思匹配,即使它包含的字符也是正则表达式元字符。
还有一些漏洞:
'...'
用作标记值分隔符。你不处理它们所有这些都可以通过使用XML解析器,然后转换DOM中的属性来解决。