【问题标题】:Extract string matching a specific format提取匹配特定格式的字符串
【发布时间】:2019-11-17 19:16:32
【问题描述】:

给定一个 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。

【问题讨论】:

    标签: regex string qt qregexp qregularexpression


    【解决方案1】:

    这里有很多方法可以提取问题中提出的部分字符串。我不知道有多少字符串格式是固定的和可变的,所以可能并非所有这些示例都是实用的。下面的一些示例还使用了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;
    

    【讨论】:

      【解决方案2】:

      也许,

      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 如何逐步消耗一些示例输入字符串并执行匹配过程。


      正则表达式电路

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

      来源

      Searching for UUIDs in text with regex

      【讨论】:

      • 正则表达式很好,我对正则表达式没有问题。我正在寻找一种从另一个字符串中提取匹配正则表达式的子字符串的有效方法。
      猜你喜欢
      • 2017-12-21
      • 1970-01-01
      • 2018-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-24
      • 2019-08-01
      相关资源
      最近更新 更多