0

<tag>=<value>正規表現を使用して型の文字列を解析しようとしていますが、引用符で囲まれた値のサポートを追加する際に問題が発生しました。アイデアは、引用符で囲まれていない値は、先頭/末尾の空白を削除して、次のようにする必要があるということです[ Hello ]( [Hello]Pls は角括弧を無視します)。

[ " 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_-]+)- 1 つ以上の英数字、またはダッシュまたはアンダースコア。これがタグとしてキャプチャされます。
  • \s*- オプションの空白の量。
  • =- 「等しい」記号。
  • \s*- オプションの空白の量。
  • "??- オプションの二重引用符 (貪欲ではない)。
  • ([%:\a-zA-Z0-9 /\._]+?)- 1 つ以上の英数字またはスペース、アンダースコア、パーセント、コロン、ピリオド、スラッシュ、バック スラッシュ。これは値としてキャプチャされます (欲張りではない)。
  • "??- オプションの二重引用符 (貪欲ではない)。
  • \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*

次に、正規表現を囲むホスト コードの 2 番目または 3 番目のキャプチャ用括弧のペアで終了する、引用されたテキストまたは引用されていないテキストの 2 つの可能性を処理する必要があります。

于 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 に答える