6

次のような有効な条件付き文字列をチェックする正規表現をjavascriptで作成したい

-1 OR (1 AND 2) AND 1

-1 OR (1 AND 2)

-1 OR 2

-1 OR 1 OR 1

-1 AND 1 AND 1

文字列に「AND」および「OR」を含めないでください。たとえば、-1 OR 2 AND 3 は無効です。- (1 OR 2) AND 3または1 または (2 AND 3)である必要があります。

次の正規表現を試しました。ほとんどの条件で機能しますが、上記の条件をチェックできません。

/^(\s*\(\d+\s(AND|OR)\s\d+\)|\s*\d+)((\s*(AND|OR)\s*)(\(\d+\s(AND|OR)\s\d+\)|\s*\d+))*$/

誰でも上記の問題を整理するのを手伝ってくれませんか。

4

2 に答える 2

5

正規表現を忘れてください。彼らはそれを行うことができません。

救助のためのパーサージェネレーター

パーサー ジェネレーターを使用すると、理解しやすく保守しやすい文法を作成できます。

これは、オンライン デモ付きの JavaScript 用のパーサー ジェネレーターです。

文法

AND私が理解したことから、との間の暗黙の優先順位規則は必要ありませんOR

有効と見なされるものの例を次に示します。

-1 OR 2 OR (2 AND 2 AND (2 OR (6 AND -2 AND (6 OR 2) AND (6 OR 2)) OR 2 OR 2))

現時点では、文法が必要/サポートしています

  • 「無限」の入れ子
  • AND/の括弧による明示的な優先順位制御OR
  • (複数の) リテラルの否定
  • オペランドと演算子の間の空白

文法簡単に変更できます

  • 任意の空白を許可する
  • 可能な複数の否定の代わりにリテラルのオプションの否定
  • 部分式の否定

より詳細な説明が必要な場合、または好みに合わせて正確に微調整する方法がわからない場合は、コメントをドロップしてください.

これがあなたの文法です。オンライン ジェネレーターに貼り付けて、をクリックしてくださいDownload parser

start
  = formula

formula
 = ors
 / ands
 / literal
 / parens_formula

parens_formula
 = "(" formula ")"

ors
 = operand (whitespace "OR" whitespace  operand)+

ands
 =  operand (whitespace "AND" whitespace operand)+

whitespace
 = " "+

operand
 = literal
 / parens_formula

literal
 = integer
 / "-" literal

integer "integer"
  = digits:[0-9]+ { return parseInt(digits.join(""), 10); }
于 2012-11-03T12:51:36.570 に答える
4

興味深い質問です。そして、phant0m の回答は非常に教育的です! (パーサーを理解している場合は使用する必要があります)。

正規表現のみを使用してこれを行う場合、次のソリューションは、JavaScript を使用して、任意にネストされた論理ステートメントを正しく検証します。

ルール/前提:

  • 有効なステートメントは、数字、括弧、スペース、AND論理演算子、および論理演算子のみで構成されORます。
  • ステートメントには、論理演算子で区切られた少なくとも 2 つの「トークン」が含まれている必要があります。各トークンは「数値」または「括弧で囲まれた単位」です。
  • +「数値」トークンは、オプションの記号 ( または のいずれか)の直前に 1 つ以上の 10 進数がある数値整数です-
  • 「括弧で囲まれた単位」トークンは、論理演算子で区切られた 2 つ以上のトークンであり、対応する開き括弧と閉じ括弧で囲まれています。
  • ステートメント全体に 3 つ以上のトークンを含めることができますが、すべてのトークンは同じ単一の演算子で区切る必要があります。またはのいずれANDOR
  • 括弧で囲まれた各ユニットには 3 つ以上のトークンを含めることができますが、すべてのトークンは同じ単一の演算子で区切る必要があります。またはのいずれANDOR
  • 任意の要素 (括弧、数値、および論理演算子) の間に任意の量の空白を使用できますが、数値と論理演算子の間には少なくとも 1 つのスペースが必要です。
  • ANDand論理演算子は、大文字とOR小文字を区別しません。

有効な論理ステートメントの例:

"1 AND 2"
"1 AND 2 AND 3"
"1 OR 2"
"-10 AND -20"
"100 AND +200 AND -300"
"1 AND (2 OR 3)"
"1 AND (2 OR 3) AND 4"
"1 OR ((2 AND 3 AND 4) OR (5 OR 6 OR 7))"
"( 1 and 2 ) AND (1 AND 2)"

無効な論理ステートメントの例:

"1x"            // Invalid character.
"1 AND"         // Missing token.
"1 AND 2 OR 3"  // Mixed logical operators.
"(1"            // Unbalanced parens.
"(((1 AND 2)))" // Too many parens.
"(1 AND) (2)"   // Missing token.
"1"             // Missing logical operator and second number
"1OR2OR3OR4"    // Missing spaces between numbers and operators.
"(1) AND (2)"   // Invalid parentheses.

正規表現ソリューション:

この問題は、ネストされた括弧で囲まれた構造を一致させる必要があり、JavaScript 正規表現エンジンは再帰式をサポートしていないため、この問題は単一の正規表現を使用して 1 回で解決することはできません。ただし、この問題は 2 つの部分に単純化でき、それぞれを1 つの JavaScript 正規表現で解決できます。最初の正規表現は最も内側の括弧で囲まれたユニットに一致し、2 番目の正規表現は簡略化された論理ステートメント (括弧を持たない) を検証します。

正規表現 #1: 最も内側の括弧で囲まれたユニットに一致します。

次の正規表現は、2 つ以上の数値トークンで構成される括弧で囲まれた 1 つの単位に一致します。ここで、数値はすべて、ANDまたはOR数値と論理演算子の間に少なくとも 1 つのスペースで区切られます。正規表現は、PHP フリースペース モードの構文で読みやすいように完全にコメント化され、フォーマットされています。

$re_paren = '/
    # Match innermost "parenthesized unit".
    \(            # Start of innermost paren group.
    \s*           # Optional whitespace.
    [+-]?\d+      # First number token (required).
    (?:           # ANDs or ORs (required).
      (?:         # Either multiple AND separated values.
        \s+       # Required whitespace.
        AND       # Logical operator.
        \s+       # Required whitespace.
        [+-]?\d+  # Additional number.
      )+          # multiple AND separated values.
    | (?:         # Or multiple OR separated values.
        \s+       # Required whitespace.
        OR        # Logical operator.
        \s+       # Required whitespace.
        [+-]?\d+  # Additional number token.
      )+          # multiple OR separated values.
    )             # ANDs or ORs (required).
    \s*           # Optional whitespace.
    \)            # End of innermost paren group.
    /ix';

正規表現 #2: 簡略化された論理ステートメントを検証します。

以下は、簡略化された論理ステートメント (数字と論理演算子のみを持ち、括弧がない) を検証する (境界アンカーを除いてほぼ同じ) 正規表現です。これは、コメント付きのフリースペース モード (PHP) 構文です。

$re_valid = '/
    # Validate simple logical statement (no parens).
    ^             # Anchor to start of string.
    \s*           # Optional whitespace.
    [+-]?\d+      # First number token (required).
    (?:           # ANDs or ORs (required).
      (?:         # Either multiple AND separated values.
        \s+       # Required whitespace.
        AND       # Logical operator.
        \s+       # Required whitespace.
        [+-]?\d+  # Additional number.
      )+          # multiple AND separated values.
    | (?:         # Or multiple OR separated values.
        \s+       # Required whitespace.
        OR        # Logical operator.
        \s+       # Required whitespace.
        [+-]?\d+  # Additional number token.
      )+          # multiple OR separated values.
    )             # ANDs or ORs (required).
    \s*           # Optional whitespace.
    $             # Anchor to end of string.
    /ix';

これら 2 つの正規表現は、境界アンカーを除いて同一であることに注意してください。

JavaScript ソリューション:

次のテスト済みの JavaScript 関数は、上記の 2 つの正規表現を使用して問題を解決します。

function isValidLogicalStatement(text) {
    var re_paren = /\(\s*[+-]?\d+(?:(?:\s+AND\s+[+-]?\d+)+|(?:\s+OR\s+[+-]?\d+)+)\s*\)/ig;
    var re_valid =  /^\s*[+-]?\d+(?:(?:\s+AND\s+[+-]?\d+)+|(?:\s+OR\s+[+-]?\d+)+)\s*$/ig;
    // Iterate from the inside out.
    while (text.search(re_paren) !== -1) {
        // Replace innermost parenthesized units with integer.
        text = text.replace(re_paren, "0");
    }
    if (text.search(re_valid) === 0) return true;
    return false;
}

この関数は、反復手法を使用して、最初に最も内側の括弧で囲まれたユニットを照合して置き換え、それぞれを単一の数字トークンに置き換えてから、結果のステートメント (括弧なし) が有効かどうかを確認します。

補遺: 2012-11-06

この回答へのコメントで、OPは、数字と演算子の間にスペースが必要であり、数字または括弧で囲まれた単位は単独で立つことはできないと述べています。これらの追加要件を念頭に置いて、上記の回答を更新しました。

于 2012-11-03T19:20:06.610 に答える