【问题标题】:Diacritical marks in regular expression causes unexpected behavior正则表达式中的变音符号会导致意外行为
【发布时间】:2020-06-27 08:35:28
【问题描述】:

我通过这个正则表达式检查名称的有效性,允许任何建议的符号here:

// Allow any symbol
const QString validNameMatcher = QStringLiteral("^[a-zA-Z0-9 _.,!()+=`,\"@$#%*-]+$");

bool Class::isNameValid(const QString fileName)
{
    QRegularExpression re(validNameMatcher);
    QRegularExpressionMatch match = re.match(fileName);

    if (match.hasMatch())
        return true;
    else
        return false;
}

对于像1111 Rick (wow) L50-57.stl 这样的文件名,上述函数返回true。到目前为止一切顺利。


为了允许变音符号,我只是按照建议的here[À-ž] 添加到名称匹配器中:

// [À-ž] is for diacritical marks
const QString validNameMatcher = QStringLiteral("^[a-zA-Z0-9À-ž _.,!()+=`,\"@$#%*-]+$");

添加[À-ž]后,令人惊讶的是,对于1111 Rick (wow) L50-57.stl的相同文件名,上述函数返回false。我错过了什么吗?


更新

根据@WiktorStribiżew 的建议,我使用了UseUnicodePropertiesOption

QRegularExpression re(validNameMatcher, QRegularExpression::PatternOption::UseUnicodePropertiesOption);

但它没有用。结果和以前一样。

(*UTF) 也不起作用:

const QString validNameMatcher = QStringLiteral("(*UTF)^[a-zA-Z0-9À-ž _.,!()+=`,\"@$#%*-]+$");

【问题讨论】:

  • 如果使用QRegularExpression::UseUnicodePropertiesOption 选项编译正则表达式会怎样?
  • @WiktorStribiżew 谢谢 =) 看起来它对我不起作用:(
  • 因此,文档会误导您说 此选项对应于 Perl 正则表达式中的 /u 修饰符。 它仅充当 (*UCP) 而不是 (*UTF) PCRE动词。试试QStringLiteral("(*UTF)^[a-zA-Z0-9À-ž _.,!()+=`,\"@$#%*-]+$")
  • @WiktorStribiżew 谢谢 =) 看起来 (*UTF) 不适合我:(
  • (*UTF) 在 QRegularExpression 中毫无意义:它适用于 QStrings,因此它只进行 Unicode 匹配。 (*UCP) 确实由该选项控制;它相当于/u(见perlre),当然不是use feature 'unicode_strings'...

标签: c++ regex qt diacritics


【解决方案1】:

关键是@WiktorStribiżew 使用QRegularExpression::UseUnicodePropertiesOption 选项的解决方案:

QRegularExpression re(validNameMatcher, QRegularExpression::PatternOption::UseUnicodePropertiesOption);

但正如其documentation 所述:

QRegularExpression::UseUnicodePropertiesOption

\w\d等的含义、字符类,以及它们对应的含义(\W、\D等) ),从仅匹配 ASCII 字符更改为匹配具有相应 Unicode 属性的任何字符。

所以,我想到将正则表达式中的 [a-zA-Z0-9À-ž_] 替换为 [\w]

// Bad:
const QString validNameMatcher = QStringLiteral("^[a-zA-Z0-9À-ž _.,!()+=`,\"@$#%*-]+$");

// Good:
const QString validNameMatcher = QStringLiteral("^[\\w .,!()+=`,\"@$#%*-]+$");

现在,isNameValid() 函数返回预期结果。

【讨论】:

    猜你喜欢
    • 2014-03-27
    • 2017-02-27
    • 2012-03-05
    • 2011-08-13
    • 1970-01-01
    • 2015-10-16
    • 2017-06-17
    • 1970-01-01
    相关资源
    最近更新 更多