0

最初に、私は SO でこの問題に対する他のすべての解決策を徹底的に調べました。それらは非常に似ていますが、私の問題を完全に解決するものはありません。

ブースト正規表現を使用して、引用符 (引用符で囲まれたもの) を除くすべてのトークンを抽出する必要があります。

私が使用する必要があると思う正規表現は次のとおりです。

sregex pattern = sregex::compile("\"(?P<token>[^\"]*)\"|(?P<token>\\S+)");

しかし、次のエラーが表示されます。

名前付きマークはすでに存在します

C# 用に投稿されたソリューションは、重複した名前付きマークで機能するようです。これは、他のマークとの OR 式であるためです。

引用符で囲まれていない限り、スペースで分割する正規表現

4

3 に答える 3

3

ここで非常によく似た質問に答えました:

私の分割を実際の1行でのみ機能させ、文字列の引用部分をスキップできるようにするにはどうすればよいですか?

サンプルコード

  • ブーストスピリットを使用
  • 引用符で囲まれた文字列、部分的に引用されたフィールド、ユーザー定義の区切り文字、エスケープされた引用符をサポート
  • 多くの (多様な) 出力コンテナーを一般的にサポートする
  • Range コンセプトのモデルを入力としてサポート (例: char[] を含む)

比較的幅広いコンパイラ バージョンと Boost バージョンでテスト済み。

https://gist.github.com/bcfbe2b5f071c7d153a0

于 2011-10-24T07:30:32.773 に答える
0

ここで答えを調べながら、別の方法をテストしました。これには、さまざまなグループマーク名を使用し、それらを反復処理するときに空白の名前をテストするだけです。これはおそらく最速のコードではありませんが、これまでで最も読みやすいソリューションであり、私の問題にとってより重要です。

これが私のために働いたコードです:

    #include <boost/xpressive/xpressive.hpp>
    using namespace boost::xpressive;
...
    std::vector<std::string> tokens;
    std::string input = "here is a \"test string\"";
    sregex pattern = sregex::compile("\"(?P<quoted>[^\"]*)\"|(?P<unquoted>\\S+)");
    sregex_iterator cur( input.begin(), input.end(), pattern );
    sregex_iterator end;

    while(cur != end)
    {
      smatch const &what = *cur;
      if(what["quoted"].length() > 0)
      {
        tokens.push_back(what["quoted"]);
      }
      else
      {
        tokens.push_back(what["unquoted"]);
      }
      cur++;
    }
于 2011-10-27T03:23:07.817 に答える
0

ほとんどの正規表現フレーバーでは、グループ名の再利用が許可されていません。一部のフレーバーでは、すべての使用が同じ代替内にある場合に許可されますが、明らかにあなたのものはそれらの1つではありません. ただし、十分に新しいバージョンの Boost を実行している場合は、ブランチ リセット グループを使用できるはずです。これは次のように見えます - (?|...|...|...)- そして、各選択肢内で、グループの番号付けは、分岐リセット グループに到達する前の場所にリセットされます。名前付きグループでも動作するはずですが、それは保証されていません。私は自分でテストする立場にないので、これを試してください:

"(?|\"(?P<token>[^\"]*)\"|(?P<token>\\S+))"

...それがうまくいかない場合は、昔ながらの番号付きグループで試してください。

于 2011-10-24T06:59:54.760 に答える