【问题标题】:perl - matching greater than charater in regexperl - 匹配大于正则表达式中的字符
【发布时间】:2020-06-01 12:49:35
【问题描述】:
$string1="<a href='/channels/folder1'>Alpha-Seeking";
$string2="<a href='/channels/folder2'>No Underlying Index ,";

我需要从上述 2 个字符串中提取“Alpha-Seeking”和“No Underlying Index”。 基本上,需要从 ('>) 到字符串最后一个字符的所有内容。

尝试了两种方法,

1) 标准直观

($string1=~ /\'>(.*?)/) {print "got $1";} 

但这似乎不适用于“>”符号。

2) 也试过了

if ($string1=~ /(?=>)(.*?)/) {print "got $1";} 

基于来自Greater than and less than symbol in regular expressions 的输入,但它不起作用。

任何输入都会很有用。

PS:另外,如果答案可以包括匹配“小于”符号(“

谢谢

【问题讨论】:

  • 如果您放弃?,第一次尝试会发生什么?
  • @stevesliva ,.. 这些引用很清楚。我修改了它们以发布此问题。已将原始问题编辑为双引号。
  • 匹配“

标签: html regex perl


【解决方案1】:

Do not parse HTML with a regex。正则表达式在解析复杂、平衡的文本(如 HTML)方面非常糟糕。

例如:

<tag>
  outer
  <tag>
    middle
    <tag>inner</tag>
    middle
  </tag>
  outer
</tag>

改为使用 HTML 解析器和搜索工具,例如 XPath

这是一个使用XML::LibXML的演示。

use strict;
use warnings;
use v5.10;

use XML::LibXML;

my $html = q{
<html>
<body>
    <a href='/channels/folder1'>Alpha-Seeking</a>
    <a href='/channels/folder2'>No Underlying Index</a>
</body>
</html>
};

# Parse the HTML
my $dom = XML::LibXML->load_html(string => $html);

# Find all links.
for my $node ($dom->findnodes('//a')) {
    # Print their text.
    say $node->textContent;
}

【讨论】:

  • 感谢@schwern,虽然它需要一些解析才能使用 HTML Parser。
【解决方案2】:

我必须首先重申,用正则表达式解析 HTML 或 XML 是非常不明智的。请考虑使用适当的 HTML 解析器。

话虽如此,您的问题很容易解决。您所谓的“标准直观方法”只需简单调整即可正常工作。

这就是你所拥有的:

if ($string1=~ /\'>(.*?)/) {print "got $1";} 

你的正则表达式是\'&gt;(.*?)。这意味着“找到一个文字引号,后跟一个大于号,然后捕获其后任何内容的最小数量”。这是“最低金额”的问题。 .*? 可以捕获的最简单的东西是空字符串。

正则表达式默认是贪婪的;它们尽可能匹配。您添加? 以消除这种贪婪并使它们尽可能少地匹配。但你不想在这里。在这里,你想要他们的贪婪。因此,只需删除 ?

use warnings;
use strict;

my @strings = (
 "<a href='/channels/folder1'>Alpha-Seeking",
 "<a href='/channels/folder2'>No Underlying Index ,"
);

for my $string (@strings) {
  if ($string =~ /'>(.*)/) { # Note: No "?" here
    print "got $1\n";
  }
}

这显示:

got Alpha-Seeking
got No Underlying Index ,

【讨论】:

  • 感谢@davecross,这行得通,但是 HTML 可以是多行的,但失败了。 +1 单线工作
  • @Aquaholic:如果您有更复杂的规格,那么最好在您的问题中提及它们,否则您将得到不是很有帮助的答案。如果要处理多行数据,则需要指定定义文本结尾的内容。
  • 同意。只是在这种情况下,在我发布了这个 q 之后,随着更多数据的暴露,它变成了额外的需求。以后会注意的。
【解决方案3】:

这对我有用

use warnings;
use strict;

my @strings = (
 "<a href='/channels/folder1'>Alpha-Seeking",
 "<a href='/channels/folder2'>No Underlying Index ,"
);

for my $string (@strings)
{
    if ($string =~ /'>(.*?)$/) 
    {
        print "got $1\n";
    } 
} 

运行它会给出

$ perl /tmp/abc.pl
got Alpha-Seeking
got No Underlying Index ,

【讨论】:

  • 感谢@pmqs,这行得通,但 HTML 可以是多行的,但失败了。 +1 单线工作。
  • @Aquaholic 同意,但您的问题表明您正在处理单行用例:-)
【解决方案4】:

在探索各种选项时,我设法使用以下方法来解决这个问题:

用其他通用符号(如管道)替换大于号

$string=~ s/>/\|/g;                 #Interestingly, '>' matches here without any issues

之后,在管道字符上拆分,并打印/解析第二部分:

    ($o1,$o2) = split(/\|/, $string);
    print "$o2|";

完美的解决方法。

【讨论】:

  • 有趣的是,'>' 在这里匹配没有任何问题 但是 '>' 总是 匹配没有任何问题。问题从来都不是'>',而是(.*?)。我以为我们已经解释过了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多