Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 在perl中使用正则表达式替换xml标记内的多行字符串_Regex_Perl - Fatal编程技术网

Regex 在perl中使用正则表达式替换xml标记内的多行字符串

Regex 在perl中使用正则表达式替换xml标记内的多行字符串,regex,perl,Regex,Perl,我已经尝试了一段时间,以使这项工作,但没有运气。这是我的文本文件(first.txt) ,my regex匹配第一个“或”和“/或”之间的多行字符串。 为什么perl不喜欢我的正则表达式?您试图捕获所有这些XML片段,这将使比赛中的事情变得过于复杂。以下正则表达式是执行替换的一种简单得多的方法: $first =~ s#(<or>\s+)<value field="id">.*?</value>(\s*</or>)#$1$content$2#sm

我已经尝试了一段时间,以使这项工作,但没有运气。这是我的文本文件(first.txt)


,my regex匹配第一个“或”和“/或”之间的多行字符串。

为什么perl不喜欢我的正则表达式?

您试图捕获所有这些XML片段,这将使比赛中的事情变得过于复杂。以下正则表达式是执行替换的一种简单得多的方法:

$first =~ s#(<or>\s+)<value field="id">.*?</value>(\s*</or>)#$1$content$2#sm;
$first=~s#(\s+).*(\s*)#$1$content$2#sm;
我使用了修饰符
s
m
,它们允许多行匹配,并允许
包含新行字符;因此,我们可以替换
开始和结束标记之间的任意数量的行。我还使用了
#
作为正则表达式的分隔符,这样我就不必费劲地转义XML close标记中的斜杠

有关正则表达式,特别是修饰符的更多信息,请参阅。

一如既往,使用正则表达式操作XMNL是一个非常糟糕的主意。为了让您看到“正确”做事是多么简单,此程序使用模块执行您的要求

  • 创建一个XML解析器对象,用于解析
    second.XML
    文件的每一行,将它们放入
    @fragments
    数组中供以后使用

  • 解析
    first.xml
    文件,然后
    findnodes
    查找所有
    元素,其中第一个元素用
    removeChildNodes
    清空,并使用
    appendChildNodes
    再次填充
    @fragments
    中的每一行

  • 最后,使用
    toString
    对XML进行格式化并打印

使用严格;
使用警告;
使用5.010;
使用自动模具;
使用XML::LibXML;
my$parser=XML::LibXML->new(无空格=>1);

打开my$fh,“首先将新值加载到数组中

然后使用
$INPLACE\u EDIT
使用如下逻辑编辑文件:

#!/usr/bin/perl
use strict;
use warnings;

my @newvals = qw(3333 4444);

while (<DATA>) {
    s{<value field="id">\K\w+(?=</value>)}{shift @newvals}e if @newvals;
    print;
}

__DATA__
<metric>
 <baseFilter>
  <and>
   <or>
    <value field="id">1111</value>
    <value field="id">2222</value>
   </or>
   <or>
    <value field="resolution" />
   </or>
</metric>
#/usr/bin/perl
严格使用;
使用警告;
my@newvals=qw(333344444);
而(){
s{\K\w+(?=)}{shift@newvals}e如果@newvals;
印刷品;
}
__资料__
1111
2222
产出:

<metric>
 <baseFilter>
  <and>
   <or>
    <value field="id">3333</value>
    <value field="id">4444</value>
   </or>
   <or>
    <value field="resolution" />
   </or>
</metric>

3333
4444

你不能只搜索
#.*\s+.*m
并替换它吗?我搜索第一个“或”和“/或”之间的字符串的原因是我可能有50个值字段行,我需要替换为第二个.txt中的任何内容。你可能应该编辑你的问题,说明在这种情况下……我觉得有人需要提及
#!/usr/bin/perl

my $first = 'first.txt';
open (my $fh, '<', $first) or die "cannot open file $first";
{
  local $/;
  $first = <$fh>;
}

$find = "([\s]+)(<or>)([\n\r\s]+).*(\n|.)+?([\n\r\s]+)(<\/or>)";

my $content = 'second.txt';
open (my $fh, '<', $content) or die "cannot open file $content";
{
 local $/;
 $content = <$fh>;
}

$first =~ s/$find/$1$2$3$content$5$6/;
print "After sub First is $first\n\n";
$first =~ s#(<or>\s+)<value field="id">.*?</value>(\s*</or>)#$1$content$2#sm;
use strict;
use warnings;
use 5.010;
use autodie;

use XML::LibXML;

my $parser = XML::LibXML->new(no_blanks => 1);

open my $fh, '<', 'second.xml';
my @fragments = map {
   chomp;
   $parser->parse_balanced_chunk($_);
} <$fh>;
close $fh;

my $xml = $parser->load_xml(location => 'first.xml');

my @or_nodes = $xml->findnodes('//or');
$or_nodes[0]->removeChildNodes;
$or_nodes[0]->appendChild($_) for @fragments;

print $xml->toString(1);
<?xml version="1.0"?>
<metric>
  <baseFilter>
    <and>
      <or>
        <value field="id">3333</value>
        <value field="id">4444</value>
      </or>
      <or>
        <value field="resolution"/>
      </or>
    </and>
  </baseFilter>
</metric>
#!/usr/bin/perl
use strict;
use warnings;

my @newvals = qw(3333 4444);

while (<DATA>) {
    s{<value field="id">\K\w+(?=</value>)}{shift @newvals}e if @newvals;
    print;
}

__DATA__
<metric>
 <baseFilter>
  <and>
   <or>
    <value field="id">1111</value>
    <value field="id">2222</value>
   </or>
   <or>
    <value field="resolution" />
   </or>
</metric>
<metric>
 <baseFilter>
  <and>
   <or>
    <value field="id">3333</value>
    <value field="id">4444</value>
   </or>
   <or>
    <value field="resolution" />
   </or>
</metric>