c++ 正则表达式(JS表示法):选择不在[ [],{},“”]中的空格以标记字符串

vhmi4jdf  于 2023-01-10  发布在  其他
关注(0)|答案(2)|浏览(65)

所以我需要用引号之外的所有空格来标记一个字符串,我在Javascript符号中使用正则表达式。
例如:

" Test Test " ab c " Test" "Test " "Test" "T e s t"

变成

[" Test Test ",ab,c," Test","Test ","Test","T e s t"]

然而,对于我的用例,解决方案应该在以下测试设置中工作:https://www.regextester.com/
所有不在引号内的空格都应该在上面的设置中突出显示。如果它们在上面的设置中突出显示,它们将在我的程序中被正确解析。
更具体地说,我使用Boost::Regex C++进行解析,如下所示:

...
std::string test_string("\" Test Test \" ab c \" Test\" \"Test \" \"Test\" \"T e s t\"");
// (,|;)?\\s+     : Split on ,\s or ;\s
// (?![^\\[]*\\]) : Ignore spaces inside []
// (?![^\\{]*\\}) : Ignore spaces inside {}
// (?![^\"].*\")  : Ignore spaces inside "" !!! MY ATTEMPT DOESN'T WORK !!!

//Note the below regex delimiter declaration does not include the erroneous regex.
boost::regex delimiter("(,|;\\s|\\s)+(?![^\\[]*\\])(?![^\\(]*\\))(?![^\\{]*\\})");
std::vector<std::string> string_vector;
boost::split_regex(string_vector, test_string, delimiter);

对于那些不使用Boost::regex或C++的人来说,上面的链接应该可以测试上述用例的可行regex。
谢谢大家的帮助,我希望你能帮助我解决上述问题。

oknwwptz

oknwwptz1#

我100%不会使用正则表达式。首先,因为用PEG grammar来表示更容易。E.g.

std::vector<std::string> tokens(std::string_view input) {
    namespace x3 = boost::spirit::x3;
    std::vector<std::string> r;

    auto atom                            //
        = '[' >> *~x3::char_(']') >> ']' //
        | '{' >> *~x3::char_('}') >> '}' //
        | '"' >> *~x3::char_('"') >> '"' //
        | x3::graph;

    auto token = x3::raw[*atom];

    parse(input.begin(), input.end(), token % +x3::space, r);
    return r;
}

这一点,现在已经按照您的预期执行了:

一个月一次

int main() {
    for (std::string const input : {R"(" Test Test " ab c " Test" "Test " "Test" "T e s t")"}) {
        std::cout << input << "\n";
        for (auto& tok : tokens(input))
            std::cout << " - " << quoted(tok, '\'') << "\n";
    }
}

输出:

" Test Test " ab c " Test" "Test " "Test" "T e s t"
 - '" Test Test "'
 - 'ab'
 - 'c'
 - '" Test"'
 - '"Test "'
 - '"Test"'
 - '"T e s t"'

奖金

这一点的真正区别在于,当您意识到希望能够处理嵌套结构(例如"string" [ {1,2,"3,4", [true,"more [string]"], 9 }, "bye ])时。
正则表达式在这方面是出了名的糟糕。不过Spirit语法规则可以是递归的。如果你把你的语法描述得更明确一些,我可以给你看例子。

vm0i2vca

vm0i2vca2#

如果你不介意的话,你可以使用多个正则表达式,我们的想法是用一个不可打印的字符(\x01)替换引号内的空格,然后在拆分后恢复它们:

const input = `" Test Test " ab c " Test" "Test " "Test" "T e s t"`;
let result = input
  .replace(/"[^"]*"/g, m => m.replace(/ /g, '\x01')) // replace spaces inside quotes
  .split(/ +/) // split on spaces
  .map(s => s.replace(/\x01/g, ' ')); // restore spaces inside quotes
console.log(result);

如果在字符串中有转义引号,例如"a \"quoted\" token",可以使用以下正则表达式:

const input = `"A \"quoted\" token" " Test Test " ab c " Test" "Test " "Test" "T e s t"`;
let result = input
  .replace(/".*?[^\\]"/g, m => m.replace(/ /g, '\x01')) // replace spaces inside quotes
  .split(/ +/) // split on spaces
  .map(s => s.replace(/\x01/g, ' ')); // restore spaces inside quotes
console.log(result);

如果你想解析嵌套的括号,你需要一个合适的语言解析器。你也可以用正则表达式来做这件事:使用JSON函数解析JavaScript对象

***了解有关regex的详细信息:***https://twiki.org/cgi-bin/view/Codev/TWikiPresentation2018x10x14Regex

相关问题