-2

私はこのような行をたくさん持っています:

13480 AAA BBB CCC

Pythonを使用して次のように変換したいと思います。

SELECT XX FROM YY WHERE SOUNDEX("AAA BBB CCC")=FIELD1 AND CP="13480"

AAA BBB CCC「 」が町であることを知っているのでAAA BBB CCC、「AAA BBB」、「AAA-BBB-CCC」、「」、「AAA」、「」L'AAA、 「 D'AAA BBB」 、「」である可能性がありますD'AAA..。さて、番号の直後の行の終わりは町の名前です。

したがって、次のような行を含む大きなファイル:

06260 Puget Théniers
06620 Bar sur Loup (Le)
06640 SAINT JEANNET
06640 Saint Jeannet
06660 AURON
06660 SAINT ETIENNE DE TINEE
06660 Saint Etienne de Tinée
06670 Levens
06710 Touët sur Var
06750 ANDON
06750 Thorenc

のようなものになってしまうだろう

SOUNDEX("Puget Théniers") AND CP="06260"
SOUNDEX("Bar sur Loup (Le)") AND CP="06620"
SOUNDEX("SAINT JEANNET") AND CP="06640"
SOUNDEX("Saint Jeannet") AND CP="06640"
SOUNDEX("AURON") AND CP="06660"
SOUNDEX("SAINT ETIENNE DE TINEE") AND CP="06660"
SOUNDEX("Saint Etienne de Tinée") AND CP="06660"
SOUNDEX("Levens") AND CP="06670"
SOUNDEX("Touët sur Var") AND CP="06710"
SOUNDEX("ANDON") AND CP="06750"
SOUNDEX("Thorenc") AND CP="06750"

始めるための最良/最もクリーンな方法は何ですか?

正規表現を使用してbashシェルでこれを実行できることは知っていますが、このような行を出力するPythonでの大きなパーサーをすでに実行しています。ですから、これらすべてをPythonで終了したいと思います。そのため、将来的にはこのような「フィルター」がたくさんある可能性があるため、クリーンなコードと説明を探しています。

[更新]13480は常に数字である必要があり、そうでない場合は例外を発生させる必要があります。

4

4 に答える 4

2
'SELECT XX FROM YY WHERE SOUNDEX("{1} {2} {3}")=FIELD1 AND CP="{0}"'\
    .format(*'13480 AAA BBB CCC'.split())

このワンライナーで十分です。正規表現を使用することもできます。

しかし、それは間違いなくあなたが使いたいものではありません。Martijnがコメントしたように、SQL式を手動で作成しないでください。SQLベースのラッパーを使用します-MySQLdbまたはユニバーサルsqlalchemy(最終的には後者になります)

あなたと一緒sqlalchemyにそのようなものになってしまうでしょう:

input_id, input_fields = input_line.split(maxsplit=1)
selection = (session.query(YY_Table)
                    .filter(YY_Table.field1=input_fields)
                    .filter(YY_Table.cp=input_id))

(これはすべて、適切なスクリプトを実行することを条件としています。データベースをマッサージする使い捨てコードを1つ作成する場合はsplit、RegExまたはVIMスクリプトを自由に使用してください)

于 2013-03-11T11:04:09.923 に答える
2

これを試してください(より複雑です):

import re
str = "13480 D'AAA-BBB CCC..."
result = re.search("([\d]+)\s([\w\s\x27\x2E\x2C\x2D]+)",str)

print(result.group(1)) # will print "13480"
print(result.group(2)) # will print "D'AAA-BBB CCC..."

超簡単な解決策:

str = "13480 D'AAA-BBB CCC..."
result = str.split(' ',1)

print(result[0]) # will print "13480"
print(result[1]) # will print "D'AAA-BBB CCC..."

ここで、group(1)とgroup(2)の結果、またはresult[0]とresult[1]の結果を使用してSQLクエリを作成する必要があります。ただし、単純な文字列操作ではなく、パラメーター化されたクエリを使用することをお勧めします(SQLインジェクションを回避するため)。

于 2013-03-11T11:14:07.953 に答える
0
# Replace yourdbms with the library of your choice
# Be sure to use the library's tokens (%s, ?, etc.)

import yourdbms

sql = """
    SELECT XX FROM YY 
    WHERE SOUNDEX(%s)=FIELD1 AND
          CP=%s
    """
conx = yourdbms.connect(your_db_info)
cursor = conx.cursor()
with open('path/to/yourfile', 'r') as f:
    for line in f:
        # Get the params without regex
        pos = line.find(' ')
        params = line[pos+1:], int(line[:pos])
        cursor.execute(sql, params)
        do_something_with(cursor)
cursor.close()
conx.close()
于 2013-03-11T11:22:39.247 に答える
0

これらの行を最初のスペースで分割するだけです。

for line in inputfile:
    code, town = line.strip().split(None, 1)

これで、この情報をさらに処理できます。これを使用してデータベースをクエリする場合、SQLクエリテキストは生成しません。代わりにSQLパラメータを使用してください。

cursor.select('SELECT XX FROM YY WHERE SOUNDEX(?)=FIELD1 AND CP=?', (town, code))

これにはいくつかの利点があります。

  1. パラメータを適切にエスケープする方法について心配する必要はありません。これは、SQLインジェクション攻撃を防ぐ場合だけでなく、入力データにSQL固有の特殊文字が含まれる可能性があるファイルからの任意のデータを処理する場合にも重要です。
  2. データベースには、ステートメントを準備する機会が与えられ、将来のクエリで再利用できるクエリプランを作成します。あなたがそのようなクエリをたくさんしているなら、それは大きな違いを生みます。
于 2013-03-11T13:30:58.410 に答える