0

次のような式をトークンに分割できる正規表現が必要です。

(6<=5) || (8+1)^2 >= 3 && 4 == 2   

結果は次のようなリストになります。

(, 6, <=, 5, ), ||, (, 8, +, 1, ), ^, 2, >=, 3, &&, 4, ==, 2

これを作成しましたが、機能しません。次の結果が得られます。

[(, 6, 5, ), (, 8, +, 1, ), ^, 2, 3, 4, 2]

これは正規表現です:

[-]?[0-9]*+([eE][-]?[0-9]+)?|([+-/*///^])|([/(/)])|(>=)|(<=)|(&&)|(==)|(||)

数字と算術記号は認識しますが、条件の記号 (&&、==、||、<=、>=) では機能しません。

それを修正する方法を知っていますか?

編集:これはコードです:

public void convertToList() {
    String regex = "[-]?[0-9]+([eE][-]?[0-9]+)?|([-+/*\\\\^])|([()])|(>=)|(<=)|(&&)|(==)|([|][|])";
    Matcher m3 = Pattern.compile(regex).matcher(this.stringExp);
    this.arrayExp = new ArrayList<String>(this.stringExp.length());
    while (m3.find()) {
        this.arrayExp.add(m3.group());
    }
}

しかし、m.butter によって修正された正規表現を使用しても機能しません (上記と同じ結果)。

編集:提供された正規表現は機能します。入力で愚かな間違いを犯しました。

4

2 に答える 2

2

式にはいくつかの問題があります。

  • -文字クラスの範囲演算子をエスケープしませんでした。 or[+-/*///^]として記述できます(最初/最後であればエスケープする必要はありません)。[+\-/*^][-+/*^]
  • |あなたはin(||)をエスケープしませんでした。(\|\|)
  • 数値の式は空の文字列と一致しますが、それは望ましくありません。

トークン化するときのヒント: オーバーラップの場合に備えて、式の最初に最長のトークンを配置します。これは、2 つではなく 1 つのトークンを取得するために<=前に置かれます。[<=]

全体として、次のようなものを使用できます。

\d+|[<>=]=|&&|\|\||[-+*/^()]

必要に応じて、より複雑な数値に置き換え\d+ます (ただし、空の文字列には一致しません)。

于 2013-06-11T11:45:18.233 に答える
1

あなたのパターンにはいくつかの問題があります。

  1. |代替として使用しています。したがって、 を使用してリテラル パイプを照合することもできません|(正規表現エンジンはどのように区別しますか?)。|したがって、文字通り一致するはずの をエスケープするか、文字クラスに入れる必要があります。

  2. あなたの脱出は間違った方法です。\スラッシュの代わりにバックスラッシュを使用する必要があります/

  3. -in a character class は、最初または最後の文字として配置しない限り、範囲を示します。[+-...]それはあなたのキャラクタークラスでは問題です。ハイフンをエスケープするか、クラスの最初または最後の位置に移動します。

  4. すべてがオプションであるため、最初の選択肢 (数値) は空の一致を許可します。これにより、不要な空の結果が大量に追加されます。*番号の後の を削除します。

それをすべて適用すると、次のようになります。

[-]?[0-9]+([eE][-]?[0-9]+)?|([-+/*\\^])|([()])|(>=)|(<=)|(&&)|(==)|([|][|])

エスケープする必要がないことに注意してください(,) , and^ inside a character class (unless the^` は最初の文字です)。

また、これを Java 文字列として記述するには、すべてのバックスラッシュを 2 つにする必要があることに注意してください。

str = "[-]?[0-9]+([eE][-]?[0-9]+)?|([-+/*\\\\^])|([()])|(>=)|(<=)|(&&)|(==)|([|][|])"

最後に、不要な括弧をすべて取り除き、必要な括弧をキャプチャしないようにすると、これをかなり最適化できます (文字クラスもマージしました)。

str = "[-]?[0-9]+(?:[eE][-]?[0-9]+)?|[-+/*\\\\^()]|>=|<=|&&|==|[|][|]"

もちろん、これは、キャプチャを使用して各一致がどの種類のトークンであったかを判断する場合を除いてのみ機能します。

ワーキングデモ

于 2013-06-11T11:46:18.337 に答える