我的QRegExp具有以下模式
QRegExp byteArray;
byteArray.setPattern("[\\x00-\\xff]*");
这种模式用于验证QString
。
有人可以举例说明哪种QString
不能通过上述模式的测试?我有一个错误,其中有一个与模式不匹配的QString。
Cand这个模式匹配任何Unicode字符串?
未通过模式验证的QString示例:HÈńr
为什么?
答案 0 :(得分:3)
QString在内部使用UTF-16,而不是UTF-8。
您还需要以\ x0001开头的QRegExp。
int main()
{
uint data[] = { 0x10c436, 0 };
QString s = QString::fromUcs4(data);
QRegExp r("^[\\x0001-\\xffff]+$");
qDebug() << s.size() << s.contains(r);
}
将导致匹配,
2 true
注意:如果您使用的是QRegularExpression,则上述内容将不再匹配。 QRegularExpression使用pcre UTF16,因此必须在PCRE代码中进行一些花哨的检查,尽管它没有报告任何错误。我没有进一步研究它。
此外,QRegularExpression接受\ x0000,但QRegExp不接受。
故事的道德是不要试图将二进制数据与正则表达式匹配。
答案 1 :(得分:2)
您在模式中提供的数字是UTF-16代码单位值(与代码点不同)。请参阅the Unicode Glossay以供参考。如果您将“HÈńr”粘贴到unicodelookup.com,您会注意到'ń'的Unicode代码点为0x144,大于0xFF,您指定为可接受范围的上限。
要接受所有Unicode字符,您需要以下表达式:
[\x0-\xFFFF]*
要仅接受第一个平面字符 - 一个代码单元(QChar
)始终对应于一个代码点的字符,您需要以下表达式:
[\x0-\xD7FF\xE000-\xFFFF]*
您对正则表达式赋予的名称byteArray
完全具有欺骗性:QString
不是字节数组,不是Unicode代码点数组,而是UTF-16代码数组单元。
第一个平面中的代码点(U + 0000到U + D7FF和U + E000到U + FFFF)以UTF-16表示为单个代码单元。 QChar
始终是代码单元。来自其他辅助平面的代码点表示为两个QChar
代码单元 - 代理对。
处理此类配对会使问题复杂化。假设你想匹配'',代码点0x10398。这表示为UTF-16中的两个代码单元:0xD800 0xDF98。模式将是:
([\xD800][\xDF98])
#include <QString>
#include <QDebug>
#include <QRegExp>
int main()
{
uint data[] = { 0x10398, 0 };
QString s = QString::fromUcs4(data);
QRegExp r("^([\\xD800][\\xDF98])$");
qDebug() << s.size() << s.contains(r);
}
输出结果为:
2 true
如果您只想匹配某些范围,比如说第一个平面和storied Linear-B Syllabary 范围是10000-1007F,您可以使用以下模式:
([\x0-\xD7FF\xE000-\xFFFF]|([\xD800][\xDC00-\xDC7F]))*
int main()
{
uint data[] = { 0x30, 0x40, 0x10000, 0x1007F, 0 };
QString s = QString::fromUcs4(data);
QRegExp r("^([\\x0-\\xD7FF\\xE000-\\xFFFF]|([\\xD800][\\xDC00-\\xDC7F]))+$");
qDebug() << s.size() << s.contains(r);
}
输出结果为:
6 true