使用正则表达式提取引用和未引用的值

时间:2013-01-18 17:43:57

标签: c++ regex boost-regex non-greedy

我试图使用正则表达式解析类型<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* - 可选数量的空格。
  • = - &#34;等于&#34;符号
  • \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]

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

2 个答案:

答案 0 :(得分:1)

我会将从第一个引号开始的部分更改为备选:

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

然后,您必须处理在正则表达式周围的主机代码中的第二个或第三个捕获括号对中结束的引用或未引用文本的两种可能性。

答案 1 :(得分:0)

弄清问题是什么。

使用\时必须小心,因为这是在C字符串中处理的,因此需要在那里进行转义,但它也会由正则表达式引擎处理,所以如果你不小心{{ 1}}变成\\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*$");