【问题标题】:Break a string in 3 parts in perl在perl中将字符串分成3部分
【发布时间】:2013-08-17 19:33:24
【问题描述】:

我有以下字符串:

my $string = "<b>My Name: John Smith < /br> </br>Rest of a big text bla bla bla …";

我想把它分成 3 个字符串。
一个有“我的名字:”
一个有“约翰·史密斯”
还有一个拥有其余文本,即其余大文本 bla bla bla
问题是“约翰史密斯”是一个变体。 IE。可以是任何名称,我想提取它。
我试过类似:
my @vals = split (/(&lt;b&gt;My Name: John Smith :*+&lt;br &gt;)/, $string); 但这甚至无法编译。
我如何在 Perl 中做到这一点?

【问题讨论】:

  • 不要使用正则表达式解析 HTML。使用适当的 HTML 解析模块。 您无法使用正则表达式可靠地解析 HTML,并且您将面临悲伤和挫败感。一旦 HTML 与您的期望发生变化,您的代码就会被破坏。有关如何使用已经编写、测试和调试过的 Perl 模块正确解析 HTML 的示例,请参阅 htmlparsing.com/perl
  • 对于这样的有限用途,正则表达式很好,事实上,或多或少有必要做一些 HTML 解析器不能/不会做的事情(例如在“我的名称”在同一标签内)。这实际上并不是解析 HTML,只是模式匹配恰好在 HTML 中的文本。
  • @AndyLester:我没有解析页面。我只需要这个字符串。它不是一个完整的页面,否则我会按照你说的做
  • split 要求您确定要返回的字符串之间的区别,但这在您的情况下很难确定,您仍然需要一些预处理或后处理来删除前导和尾随文本。 split 不是正确的选择。
  • 为了解释@Sinan Ünür 的评论,在 HTML 中应该是 &lt;br&gt;,在 XHTML 中应该是 &lt;br&gt;&lt;/br&gt;&lt;br/&gt;&lt;/br&gt; 单独在两者中均无效。

标签: regex perl html-parsing


【解决方案1】:

一个简单的正则表达式应该可以工作。

my ($label, $name, $rest) = $string =~ m=<b>(.*?): (.*?) < /br> </br>(.*)=;
print "$label\n$name\n$rest\n";

请注意,&lt;/ 之间的空格不是 HTML 中的正确语法,可能无法按您希望的方式呈现。

顺便说一句,你有没有注意到字符串中包含字符 U+2026?

【讨论】:

  • 没有。你是怎么注意到的?
  • @Jim:我将字符串粘贴到我的编辑器(emacs)中,它告诉我它无法以纯 ASCII 格式保存。
  • 仅供参考,U+2026为
【解决方案2】:
#!/usr/bin/env perl

use utf8;
use 5.014;
use strict;
use warnings;
use open qw(:std :utf8);

use HTML::TokeParser::Simple;

my $html = q{<b>My Name: John Smith <br /> <br />Rest of a big text bla bla bla …};

my $parser = HTML::TokeParser::Simple->new(string => $html);

while (my $tag = $parser->get_tag('b')) {
    my $text = $parser->get_text('br');
    next unless my ($label, $name) = ($text =~ m{\A (My Name:) \s+ (.+) }xs);
    $name =~ s{\s+\z}{};
    $text = $parser->get_text('/b');
    $text =~ s{\A\s+}{};
    $text =~ s{\s+\z}{};
    say "|$_|" for $label, $name, $text;
}

【讨论】:

    【解决方案3】:
    my $string = "<b>My Name: John Smith < /br> </br>Rest of a big text bla bla bla …";
    
    my @vals = 
      map { /(My Name:)\s*(.+)/ ? ($1,$2) : $_ } 
      grep length,
      split /\s* <.+?> \s*/x, $string;
    
    use Data::Dumper; print Dumper \@vals;
    

    输出

    $VAR1 = [
              'My Name:',
              'John Smith',
              'Rest of a big text bla bla bla .'
            ];
    

    【讨论】:

    • 如果&lt;b&gt; 丢失怎么办?
    • @Jim 好点;顺便说一句,您可以依赖字符串的哪些部分?
    【解决方案4】:

    使用正则表达式和预定义变量“$'”,它指的是字符串中匹配正则表达式的部分之后的部分!

    【讨论】:

      猜你喜欢
      • 2014-04-07
      • 2010-11-27
      • 2022-08-10
      • 1970-01-01
      • 2020-05-16
      • 1970-01-01
      • 1970-01-01
      • 2014-01-26
      • 1970-01-01
      相关资源
      最近更新 更多