将字符串与转义字符或反斜杠匹配

时间:2016-01-06 00:29:33

标签: regex perl

以下perl脚本和TestData模拟了我只能找到2而不是4个预期的情况。 (以匹配所有support.tier.1与中间的反斜杠。)

如何在此处修改此perl正则表达式?感谢

my @TestData(
    "support.tier.1",
    "support.tier.2",
    qw("support\.tier\.1"),
    "support\.tier\.2",
    quotemeta("support.tier.1\@example.com"),
    "support.tier.2\@example.com",
    "support\.tier\.1\@example\.com",
    "support\.tier\.2\@example\.com",
    "sales\@example\.com"
);

以下是要更改的代码:

my $count = 0;
foreach my $tier(@TestData){
    if($tier =~ m/support.tier.1/){
        print "$count: $tier\n";
    }
    $count++;
}

我只得到2场比赛,而预期的是4场比赛:

0: support.tier.1
6: support.tier.1@example.com

2 个答案:

答案 0 :(得分:3)

更新

由于您似乎确实可以获得包含反斜杠的字符串,因此我建议您在测试字符串之前使用String::Unescape删除这些反斜杠。您可能必须安装它,因为它不是核心模块

您的代码看起来像这样

use strict;
use warnings;

use String::Unescape;

my @tiers = (
  "support.tier.1",
  "support.tier.2",
  qw("support\.tier\.1"),
  "support\.tier\.2",
  quotemeta("support.tier.1\@example.com"),
  "support.tier.2\@example.com",
  "support\.tier\.1\@example\.com",
  "support\.tier\.2\@example\.com",
  "sales\@example\.com",
);

my $count = 0;

for my $tier ( @tiers ) {

  my $plain = String::Unescape->unescape($tier);

  if ( $plain =~ /support\.tier\.1/ ) {
    printf "%d: %s\n", ++$count, $tier;
  }
}

输出

1: support.tier.1
2: "support\.tier\.1"
3: support\.tier\.1\@example\.com
4: support.tier.1@example.com

请注意,String::Unescape模块中存在一个错误,导致其无法导出unescape功能。这只是意味着您必须始终使用String::Unescape::unescapeString::Unescape->unescape。或者您可以使用*unescape = \&String::Unescape::unescape

手动导入它


@tiers数组包含这些确切的字符串

  1. support.tier.1
  2. support.tier.2
  3. "support\.tier\.1"
  4. support.tier.2
  5. support\.tier\.1\@example\.com
  6. support.tier.2@example.com
  7. support.tier.1@example.com
  8. support.tier.2@example.com
  9. sales@example.com
  10. 你能看到只有第1和第7项包含字符串support.tier.1吗?我想你想要匹配的另外两个是3和5,其中包含虚假的反斜杠

    目前尚不清楚,但您似乎不太可能以此格式获取数据。如果你真的想匹配support.tier.1,其中任何一个点前面都有一个反斜杠字符,那么你需要/support\\?\.tier\\?\.1/,但我认为你误解了Perl字符串的工作方式

答案 1 :(得分:2)

我可能不完全明白,但如果我这样做,我同意马特已经试图给你的答案。如果您在support.tier.1中的每个句点之前说出转义字符可能会或可能不会出现,那么正则表达式肯定可以处理您的请求。

单个反斜杠为\\?表示“一个或零”:

use strict;
use warnings;

my @tiers = (
  "support.tier.1",
  "support.tier.2",
  qw("support\.tier\.1"),
  "support\.tier\.2",
  quotemeta("support.tier.1\@example.com"),
  "support.tier.2\@example.com",
  "support\.tier\.1\@example\.com",
  "support\.tier\.2\@example\.com",
  "sales\@example\.com",
);

my $count = 0;

foreach my $tier (@tiers) {
  if ($tier =~ /support\\?.tier\\?.1/) {
    print "$count: $tier\n";
  }
  $count++;
}

在一个不相关的说明中,为了创建一个易于理解的示例,我提供了一个建议,说明如何更好地格式化示例数据,而不是使用$strpush es

如果有效,我建议你让马特发表评论回复作为答案并接受。