提取匹配特定格式的字符串

时间:2019-11-17 19:16:32

标签: regex string qt qregexp qregularexpression

给出一个QString,我想从主字符串输入中提取一个子字符串。

例如我有一个QString阅读类似:

\\\\?\\Volume{db41aa6a-c0b8-11e9-bc8a-806e6f6e6963}\\

我需要使用匹配正则表达式格式(\w){8}([-](\w){4}){3}[-](\w){12}的模板/格式来提取字符串(如果存在具有格式的字符串),如下所示:

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

它应该返回

db41aa6a-c0b8-11e9-bc8a-806e6f6e6963

如果找到,则为空QString

目前,我可以通过执行以下操作来实现此目的:

string.replace("{", "").replace("}", "").replace("\\", "").replace("?", "").replace("Volume", "");

但这是乏味且效率低下的,并且是针对特定要求量身定制的。

是否存在使我能够使用正则表达式格式或其他格式提取子字符串的通用函数?

更新

为清晰起见,在@Emma回答后,我想要QString::extract("(\w){8}([-](\w){4}){3}[-](\w){12}")返回db41aa6a-c0b8-11e9-bc8a-806e6f6e6963

2 个答案:

答案 0 :(得分:2)

有很多方法可以提取问题中提出的字符串的一部分。我不知道固定和可变的字符串格式有多少,因此可能并非所有这些示例都是实用的。下面的一些示例也使用QStringRef类,该类效率更高,但在任何引用处于活动状态时(请参阅文档中的警告),必须具有原始字符串(被引用的字符串)。

  const QString str("\\\\?\\Volume{db41aa6a-c0b8-11e9-bc8a-806e6f6e6963}\\");

  // Treat str as a list delimited by "{" and "}" chars.

  const QString sectResult = str.section('{', 1, 1).section('}', 0, 0);  // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"
  const QString sectRxResult = str.section(QRegExp("\\{|\\}"), 1, 1);    // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"

  // Example using QStringRef, though this could also be just QString::split() which returns QString copies.
  const QVector<QStringRef> splitRef = str.splitRef(QRegExp("\\{|\\}"));
  const QStringRef splitRefResult = splitRef.value(1);  // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"

  // Use regular expressions to find/extract matching string

  const QRegularExpression rx("\\w{8}(?:-(\\w){4}){3}-\\w{12}");  // match a UUID string
  const QRegularExpressionMatch match = rx.match(str);
  const QString rxResultStr = match.captured(0);        // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"
  const QStringRef rxResultRef = match.capturedRef(0);  // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"

  const QRegularExpression rx2(".+\\{([^{\\}]+)\\}.+");  // capture anything inside { } brackets
  const QRegularExpressionMatch match2 = rx2.match(str);
  const QString rx2ResultStr = match2.captured(1);       // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"
  // Make a copy for replace so that our references to the original string remain valid.
  const QString replaceResult = QString(str).replace(rx2, "\\1");   // = "db41aa6a-c0b8-11e9-bc8a-806e6f6e6963"

  qDebug() << sectResult << sectRxResult << splitRefResult << rxResultStr
           << rxResultRef << rx2ResultStr << replaceResult;

答案 1 :(得分:0)

也许

Volume{(\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b)}

或者只是

\b[0-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-f]{12}\b

完整比赛可能会更近一些。


如果您想简化/更新/探索表达式,请在regex101.com的右上角进行解释。如果您有兴趣,可以观看匹配的步骤或在this debugger link中进行修改。调试器演示了a RegEx engine如何逐步使用一些示例输入字符串并执行匹配过程的过程。


RegEx电路

jex.im可视化正则表达式:

enter image description here

来源

Searching for UUIDs in text with regex