regex - 从已截断为不同长度的字符串末尾删除单词

标签 regex perl

假设我有一个字符串列表,有时以一个被截断为不同长度的短语结尾。在这个例子中,短语是“你好”。

my @strings =
(
    "Test 1 hello",
    "Something else",
    "Test 2 hell",
    "And also he",
    "Test 4 hel"
);

这就是我现在删除“hello”片段的方式:

foreach my $string (@strings)
{
    if ($string =~ m/(.*?)\s*(h(e(l(lo?)?)?)?)?$/)
    {
        print "'", $string, "' -> '", $1, "'\n";
    }
}

它确实有效:

'Test 1 hello' -> 'Test 1'
'Something else' -> 'Something else'
'Test 2 hell' -> 'Test 2'
'And also he' -> 'And also'
'Test 4 hel' -> 'Test 4'

但是,我发现匹配所有“hello”片段的正则表达式很长、令人困惑并且难以为将来的用例修改。 有没有更短的方法来编写等同于 (h(e(l(lo?)?)?)?)?$?

最佳答案

构建正则表达式的一种方法是交替使用可能的字符串版本。我认为这也应该很好地扩展到更一般的用途

use warnings;
use strict;
use feature 'say';

my $target = shift || 'hello';

my @strings = (
    "Test 1 hello",
    "Something else",
    "Test 2 hell",
    "And also he",
    "Test 4 hel"
);

my $re_versions = build_regex($target);

foreach my $string (@strings)
{
    if ($string =~ /($re_versions)$/)
    {
        say "'$string' --> $1";
    }
};

sub build_regex {
    my ($s) = @_;
    my @versions;
    while ($s) {
        push @versions, quotemeta $s;
        chop $s;
    }
    return join '|', @versions;
}

这并不短(虽然它肯定可以以更短的方式编写)但它应该易于管理以改进可接受的字符串版本、匹配顺序等。

如果有理由想要返回已编译的正则表达式,请将函数返回更改为

my $re_str = join '|', @versions;
return qr/$re_str/;

您现在还可以在其中添加可能合适的标志。

关于regex - 从已截断为不同长度的字符串末尾删除单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53907595/

相关文章:

c++ - C/C++ 或其他语言中的 SOCKS?

c# - 正则表达式匹配不正确的值

java - 如何只替换标记,没有子字符串?

regex - 如何在正则表达式中指定单引号

数组文字上的 perl smartmatch

regex - 在perl中对文本 block 进行排序

perl 脚本,只会打印 tomcat 版本

regex - 如何在 Apache RewriteRule 中向正则表达式添加 +(加号)?

regex - bash:如何检查字符串是否以 '#' 开头?

perl - 使用 Excel::Writer::XLSX 导出大型数据集时遇到问题