実現したいこと
- ターゲット文字列(=ユーザー入力)に対して,予め定義済の特定パターン字句(但し複数句含む)を用いてパースする。
- 上記特定パターン字句を含むならば,パターン該当文字列を抜き出す。
- 上記特定パターン字句内の特定文字列と比較して,
ターゲット文字列が非該当文字を含んでいれば,当該文字列をエラー対象としてエラー表示する。
※ 特定パターン字句内の特定文字列とは具体的に,
SQLデータベースのカラム名に該当する単なる文字列です。
ターゲット文字列内のカラム名相当文字列がこのデータベースカラム名文字列に完全合致するか否かを識別したいです。
※ ターゲット文字列は,特定パターン字句を複数句含む場合を想定しています。
発生している問題・分からないこと
下記のソースコード内に, コメントとして, 実行結果あるいは注釈を記述しています。
A. クエリ列文字列に対して,ターゲット文字列内のクエリ列文字列相当が完全合致していれば,正常処理出来ます。
B. クエリ列文字列に対して,ターゲット文字列内のクエリ列文字列相当が非合致分を含んでいると,
複数句全てを検知することが出来なくなり,そして,その原因となった文字をエラー表示することが出来ません。
→ この,検知出来た特定パターン字句のみを解析結果とするという挙動は,一見正しい挙動のようにも見えます。
ですが,エラーとなった特定パターン字句を明確化し,その原因となった文字をエラー表示したいとも思っています。
該当のソースコード
Python
1from pyparsing import * 2 3def define_grammer(num): # 解析構文は最終的に1つだが,質問の為に選択式に改変している。 4 # クエリ列候補 5 query_header = ["ID", "名前", "誕生日"] 6 クエリ列候補 = oneOf(query_header) 7 8 # 解析文字列 9 クエリ列文字列 = Suppress('"') + クエリ列候補 + Suppress('"') 10 LIKE = Keyword('LIKE') 11 検索文字列 = Combine(Suppress('"') + Word(alphas) + Suppress('"')) 12 AND = Keyword('AND') 13 # クエリ構文(1句) 14 クエリ構文1 = Group(クエリ列文字列 + LIKE + 検索文字列) 15 16 # 解析構文例 17 grammer = [] 18 grammer.append(クエリ構文1 + ZeroOrMore(AND)) # クエリ構文[0] ・・・ 1句 19 grammer.append(クエリ構文1 + ZeroOrMore(AND) + クエリ構文1 + ZeroOrMore(AND)) # クエリ構文[1] ・・・ 2句 20 grammer.append(ZeroOrMore(クエリ構文1 + ZeroOrMore(AND))) # クエリ構文[2] ・・・ ZeroOrMoreで複数句のつもり(★) 21 # クエリ構文が複数句,かつ,クエリ文字列の誤検出文字列を検知する(以下 "S"等)場合に於いて,★をどう記述したら良いかが分からない。 22 rgrammer = grammer[num] 23 return rgrammer 24 25def test_parse(grammer, target_string): 26 try: 27 parseresults = grammer.parse_string(target_string) 28 print(parseresults) 29 except ParseException as pe: 30 print(f"{pe.explain(depth=0)}") 31 print() 32 return 33 34 35if __name__ == '__main__': 36 # パーステスト (コメント文は,上記のParseException内容) 37 38 # ParseException: Expected ID | 名前 | 誕生日, found 'sID' (at char 1), (line:1, col:2) -> クエリ列文字列に非合致。検知出来ている。 39 grammer = define_grammer(0) 40 test_parse(grammer, '"SID"') 41 42 # ParseException: Expected '"', found 'S' (at char 3), (line:1, col:4) -> クエリ列文字列に非合致。誤検出文字列(S)を検知出来ている。(◎) 43 grammer = define_grammer(0) 44 test_parse(grammer, '"IDS"') 45 46 # [['ID', 'LIKE', 'a']] -> クエリ列文字列に合致。 47 grammer = define_grammer(0) 48 test_parse(grammer, '"ID" LIKE "a"') 49 50 # [['ID', 'LIKE', 'a'], 'AND', ['名前', 'LIKE', 'b']] -> クエリ列文字列に合致。 51 grammer = define_grammer(1) 52 test_parse(grammer, '"ID" LIKE "a" AND "名前" LIKE "b"') 53 54 # [['ID', 'LIKE', 'a'], 'AND', ['名前', 'LIKE', 'b']] -> クエリ列文字列に合致。 55 grammer = define_grammer(2) 56 test_parse(grammer, '"ID" LIKE "a" AND "名前" LIKE "b"') 57 58 # [['ID', 'LIKE', 'a'], 'AND'] -> クエリ列文字列2句目が欠落しており,さらに誤検知がされていない。ここで◎のように誤検知したい。 59 grammer = define_grammer(2) 60 test_parse(grammer, '"ID" LIKE "a" AND "名前S" LIKE "b"')
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
どうやら,
特定パターン句を複数句化(=ZeroOfMore/OneOfMore)した瞬間に,
oneOf(=本来は前方部分一致だが,
前後に文字列""を組み合わせることで完全合致判定のようなことが出来るようになっている模様)
が作用しなくなっているように思います。
特定パターン字句を明示的に回数分だけ記述すれば意図するように動作するようですが,
この複数回を簡潔に書ける方法を知りたいと思い,こちらに質問させて頂いています。
- 特定パターン字句の再帰化? ・・・ 再帰関数で対応可能?? 私には分かりませんでした。
- ソースコードの改変 ・・・ pyparsing oneOf関数について,完全合致の実現を試みましたが,上記ソースコードに落ち着きました。
補足
pyparsing 3.2.1
回答1件
あなたの回答
tips
プレビュー