0

我正在尝试<tag>=<value>使用正则表达式解析一个类型的字符串,但是遇到了一些添加对引用值的支持的问题。这个想法是任何未引用的值都应该被修剪掉前导/尾随空格,这样[ Hello ]就变成[Hello]了(请忽略方括号。)

但是,当引用该值时,我希望删除包括双引号在内的任何内容,但不再赘述,因此[ " Hello World " ]将变为[" Hello World "]

到目前为止,我已经提出了以下带有模式匹配的代码(请注意,某些字符已被转义或双重转义,以避免将它们解释为三字符图或其他 C 格式字符。)

void getTagVal( const std::string& tagVal )
{
    boost::smatch what;
    static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\a-zA-Z0-9 /\\._]+?)\"\?\?\\s*$");

    if ( boost::regex_match( tagVal, what, pp ) )
    {
        const string tag = static_cast<const string&>( what[1] );
        const string val = static_cast<const string&>( what[2] );

        cout << "Tag = [" << tag << "] Val = [" << val << "]" << endl;
    }
}

int main( int argc, char* argv[] )
{
    getTagVal("Qs1= \" Hello World \" ");
    getTagVal("Qs2=\" Hello World \" ");
    getTagVal("Qs3= \" Hello World \"");
    getTagVal("Qs4=\" Hello World \"");
    getTagVal("Qs5=\"Hello World \"");
    getTagVal("Qs6=\" Hello World\"");
    getTagVal("Qs7=\"Hello World\"");

    return 0;
}

取出双重转义,这分解为:

  • ^- 线的开始。
  • \s*- 可选数量的空白。
  • ([a-zA-Z0-9_-]+)- 一个或多个字母数字或破折号或下划线。这被捕获为标签。
  • \s*- 可选数量的空白。
  • =- 一个“相等”的符号。
  • \s*- 可选数量的空白。
  • "??- 一个可选的双引号(非贪婪)。
  • ([%:\a-zA-Z0-9 /\._]+?)- 一个或多个字母数字或空格、下划线、百分比、冒号、句点、正斜杠或反斜杠。这被捕获为值(非贪婪)。
  • "??- 一个可选的双引号(非贪婪)。
  • \s*- 可选数量的空白。
  • $- 行结束

对于中的示例调用main(),我希望得到:

Tag = [Qs1] Val = [ Hello World ]
Tag = [Qs2] Val = [ Hello World ]
Tag = [Qs3] Val = [ Hello World ]
Tag = [Qs4] Val = [ Hello World ]
Tag = [Qs5] Val = [Hello World ]
Tag = [Qs6] Val = [ Hello World]
Tag = [Qs7] Val = [Hello World]

但我实际得到的是:

Tag = [Qs1] Val = [" Hello World ]
Tag = [Qs2] Val = [" Hello World ]
Tag = [Qs3] Val = [" Hello World ]
Tag = [Qs4] Val = [" Hello World ]
Tag = [Qs5] Val = ["Hello World ]
Tag = [Qs6] Val = [" Hello World]
Tag = [Qs7] Val = ["Hello World]

所以它几乎是正确的,但由于某种原因,第一个引号在输出值中徘徊,即使我特别将正则表达式的值部分与它外面的引号括起来。

4

2 回答 2

1

我将从第一个引用开始的部分更改为替代:

"([^"]+)"|([%:\a-zA-Z0-9 /\._]+)\s*

然后,您将不得不处理引用或未引用文本的两种可能性,这些文本最终出现在正则表达式周围的主机代码中的第二个或第三个捕获括号对中。

于 2013-01-18T17:53:52.593 回答
0

弄清楚问题出在哪里。

使用\时必须小心,因为这是在 C 字符串中处理的,因此需要在那里转义,但它也会由正则表达式引擎处理,所以如果你不小心\\a\a这绝对不是你想要的。

所以,要告诉它我希望 a\出现在我的值中的字符集中(讽刺的是,它们被用作格式字符串中的转义序列),那么你必须对它们进行双重转义

static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\a-zA-Z0-9 /\\._]+?)\"\?\?\\s*$");

变成:

static const boost::regex pp("^\\s*([a-zA-Z0-9_-]+)\\s*=\\s*\"\?\?([%:\\\\a-zA-Z0-9 /._]+?)\"\?\?\\s*$");

(即你需要做到\\\\

于 2013-01-18T18:16:02.313 回答