【问题标题】:Regex to get a combination of constant and pattern正则表达式获得常量和模式的组合
【发布时间】:2016-11-07 09:20:02
【问题描述】:

我正在研究一个正则表达式,它可以帮助我替换字符串中的模式。

我在流中的字符串很长,应用正则表达式后(查找模式,然后用常量值替换)我必须将字符串转发到我的 ETL 流中。

To find:
<customer attribute="any number">
 like <customer attribute="1">
and replace with:
<customer>. (basically just keep "customer" and delete everything) 

我是 Regex 的新手并正在学习它。

任何帮助!

【问题讨论】:

  • $str=~s/&lt;customer[^&gt;]*attribute="([^\"]*)"[^&gt;]*&gt;/&lt;customer&gt;/g; 这里的属性可以改组,或者可以有多个属性,因此我们使用[^&gt;]*
  • 听起来很可疑,就像您正在使用正则表达式解析 XML。如果是这样:这是个坏主意,请改用XML::Twig。 (发布一些 XML 和所需的输出,我会给你一个正确的例子)
  • @ssr1012 - 不工作:(
  • 提供您的意见。
  • @vikas - 请将edit 加入您的帖子中。

标签: perl pentaho regex-negation kettle pdi


【解决方案1】:

请,请,请。 Don't use regular expressions to parse XML

这是个坏消息。它既脆弱又笨拙,最重要的是 - 完全没有必要。

正则表达式不处理上下文。 XML 是关于上下文的。

XML 已经有一个更适合的查询语言xpath

这是一个使用xpath查找节点的示例。

#!/usr/bin/env perl

use strict;
use warnings;
use XML::Twig;

my $twig = XML::Twig -> new -> parsefile ('yourfile.xml'); 

print $twig -> get_xpath('//consumer', 0) -> att('attribute'),"\n";

但如果你想改造它并删除attribute

$_ -> del_att('attribute') for $twig -> get_xpath('//consumer[@attribute]');
$twig -> set_pretty_print('indented_a');
$twig -> print;

不过我会问 - 你为什么要这样做?这听起来更像是某个地方的另一个损坏的过程——也许另一个脚本试图regex XML?

但是XML::Twig 做得很好的另一件事真正是它有twig_handlers 可以让您更整洁地处理 XML 流(例如,无需将其全部解析到内存中。

有点像这样:

#!/usr/bin/env perl

use strict;
use warnings;
use XML::Twig;

sub delete_unwanted {
    my ( $twig, $element ) = @_; 
    $element -> del_att('attribute'); 
    #dump progress so far 'out'. 
    $twig -> flush; 
    #free memory already processed. 
    $twig -> purge; 
}

my $twig = XML::Twig -> new ( twig_handlers => { '//consumer[@attribute]' => \&delete_unwanted } );
   $twig -> parsefile ( 'your_xml.xml'); 

我们设置了一个处理程序,以便每次解析器遇到带有attribute 属性的consumer。 (不好的名字)它删除它,flushes(打印)解析的 XML,并从内存中清除它。这使得它非常节省内存,因为您没有将整个内容读入内存,并且可以执行几乎所有内联正则表达式类型的操作。

【讨论】:

  • OP 正在谈论一个流。这将是宣传 XML::Twig 处理分块数据的能力的好地方。
  • @Sobrique。首先非常感谢您的宝贵时间。你很好地阐述了这一点。但就我而言,我正在使用 Penatho Kettle 制作我的 XML 初稿。然后做了很多操作,为了遍历目的,我添加了“属性”。最后我需要删除它。
  • 嗯,听起来您可能正在以不太理想的方式解决此问题。您将 XML 传递给的大多数东西,如果属性是多余的......它将是无关紧要的。这就是 XML 的重点。
【解决方案2】:

输入:

&lt;consumer attribute=\"1\"&gt;&lt;birth-date&gt;1990-07-23&lt;/birth-date&gt; &lt;/consumer&gt;;

my $element_name = "consumer";

my $str = "<consumer attribute=\"1\"><birth-date>1990-07-23</birth-date> </consumer>";

$str=~s/<($element_name)[^>]*attribute="[^\"]*"[^>]*>/<$1>/g;

print $str;

输出:

&lt;consumer&gt;&lt;birth-date&gt;1990-07-23&lt;/birth-date&gt; &lt;/consumer&gt;

【讨论】:

  • @DaveCross:如果这样做,您会在任何帖子中指出吗?我确信我不鼓励使用 XML 转换的正则表达式。我刚刚转发了正则表达式中查询的答案。足够。感谢您的反对。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 1970-01-01
相关资源
最近更新 更多