【问题标题】:Perl unite 2 regexps into 1Perl 将 2 个正则表达式合并为 1 个
【发布时间】:2021-11-19 14:33:45
【问题描述】:

有效的字符串应该由西里尔字符或拉丁字符组成。

我用 2 个正则表达式创建了一个可行的解决方案。但是当我尝试将它们合并为 1 时,它失败了:

#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use v5.14;
use open ':std', ':encoding(UTF-8)';

my @data = (
    # rus - ok
    "абвгдеёжзийклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ",
    # space
    "а бвгдеёжзийклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ",
    # rus - latin
    "аtбвгдеёжзийклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ",
    # digit
    "аб2вгдеёжзийклмнопрстуфхцчшщьыъэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ",
    # latin - ok
    "abcdefghejklmnopqrstuvwxyzABCDEFGHEJKLMNOPQRSTUVWXYZ",
    # space
    "a bcdefghejklmnopqrstuvwxyzABCDEFGHEJKLMNOPQRSTUVWXYZ",
    # underscore
    "a_bcdefghejklmnopqrstuvwxyzABCDEFGHEJKLMNOPQRSTUVWXYZ",
    # digit
    "a2bcdefghejklmnopqrstuvwxyzABCDEFGHEJKLMNOPQRSTUVWXYZ"
);

foreach(@data) {
    if ($_ =~ /^[а-яё]+$/i or $_ =~ /^[a-z]+$/i) {
        print "ok\n";
    }
    else {
        print "bad\n";
    }
}

print "-------\n";
foreach(@data) {
    if ($_ =~ /^(:?[а-яё]+)|(:?[a-z]+)$/i) {
        print "ok\n";
    }
    else {
        print "bad\n";
    }
}

输出:

ok
bad
bad
bad
ok
bad
bad
bad
-------
ok
ok
ok
ok
ok
ok
ok
ok

由于某种原因,第二个正则表达式总是成功。

【问题讨论】:

    标签: regex perl


    【解决方案1】:

    在你的正则表达式中,

    • :? - 匹配可选的:,而您想定义non-capturing group(?:...)
    • ^(?:a+)|(?:b+)$ - 匹配字符串开头的 as 或字符串结尾的 bs。

    你应该使用

    /^(?:[а-яё]+|[a-z]+)$/i
    

    请参阅regex demo详情

    • ^ - 字符串开头
    • (?: - 非捕获组的开始
      • [а-яё]+ - 一个或多个俄语字母
      • | - 或
      • [a-z]+ - 一个或多个 ASCII 字母
    • ) - 非捕获组结束
    • $ - 字符串结束。

    注意:从 Perl 5.22 开始,您可以使用 n modifier 使捕获组表现为非捕获,/^([а-яё]+|[a-z]+)$/ni。所以,混合?::? 是没有风险的。

    在这种情况下使用use v5.22.0; 检查核心版本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-21
      • 2011-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      相关资源
      最近更新 更多