-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 shell 中执行此操作,但我已经在 python 中完成了一个大解析器,它输出这样的行。所以我想用 Python 完成所有这些,这就是为什么我正在寻找一个干净的代码和一些解释,因为我将来可能有很多这样的“过滤器”要做。

[update]13480应该始终是数字,如果不是,则应引发异常。

4

4 回答 4

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 回答
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))

(所有这一切的前提是你编写了一个正确的脚本。如果你编写一个一次性的代码来按摩你的数据库,那么请随意使用splitRegEx 甚至 VIM 脚本)

于 2013-03-11T11:04:09.923 回答
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 回答
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 回答