让Python的正则表达式使用变量进行字符串表达式

4 投票
2 回答
1187 浏览
提问于 2025-04-16 21:02

我有一个.csv文件,里面包含了我想要匹配的正则表达式模式,还有我想要的替换模式。有些模式非常简单,比如把"."替换成""或者把","替换成""。

但是,当我运行下面的代码时,它似乎没有识别到变量,模式也从来没有被匹配到。

                f = open('normalize_patterns.csv', 'rU')
                c = csv.DictReader(f)
                for row in c:
                    v = re.sub(row['Pattern'],row['Replacement'],v)

之后,变量v从来没有改变,我也找不到原因。当我运行一个简单的例子时

                v = re.sub("\.", "", v)
                v = re.sub(",", "", v)

结果是所有的句号和逗号都被去掉了。关于这个问题的任何帮助都非常感谢!提前谢谢你们!(我很确定这个.csv文件格式是正确的,我只用"."和""的情况运行过,还是没有成功,原因不明)

编辑:
这是打印row的输出。(谢谢David!)

{'Pattern': "r'(?i)&'", 'ID': '1', 'Replacement': "'and'"}
{'Pattern': "r'(?i)\\bAssoc\\b\\.?'", 'ID': '2', 'Replacement': "'Association'"}
{'Pattern': "r'(?i)\\bInc\\b\\.?'", 'ID': '3', 'Replacement': "'Inc.'"}
{'Pattern': "r'(?i)\\b(L\\.?){2}P\\.?'", 'ID': '4', 'Replacement': "''"}
{'Pattern': "r'(?i)\\bUniv\\b\\.?'", 'ID': '5', 'Replacement': "'University'"}
{'Pattern': "r'(?i)\\bCorp\\b\\.?'", 'ID': '6', 'Replacement': "'Corporation'"}
{'Pattern': "r'(?i)\\bAssn\\b\\.?'", 'ID': '7', 'Replacement': "'Association'"}
{'Pattern': "r'(?i)\\bUnivesity\\b'", 'ID': '8', 'Replacement': "'University'"}
{'Pattern': "r'(?i)\\bIntl\\b\\.?'", 'ID': '9', 'Replacement': "'International'"}
{'Pattern': "r'(?i)\\bInst\\b\\.?'", 'ID': '10', 'Replacement': "'Institute'"}
{'Pattern': "r'(?i)L\\.L\\.C\\.'", 'ID': '11', 'Replacement': "'LLC'"} 
{'Pattern': "r'(?i)Chtd'", 'ID': '12', 'Replacement': "'Chartered'"}
{'Pattern': "r'(?i)Mfg\\b\\.?'", 'ID': '13', 'Replacement': "'Manufacturing'"}
{'Pattern': 'r"Nat\'l"', 'ID': '14', 'Replacement': "'National'"}
{'Pattern': "r'(?i)Flordia'", 'ID': '15', 'Replacement': "'Florida'"}
{'Pattern': "r'(?i)\\bLtd\\b\\.?'", 'ID': '16', 'Replacement': "'Ltd.'"}
{'Pattern': "r'(?i)\\bCo\\b\\.?'", 'ID': '17', 'Replacement': "'Company'"}
{'Pattern': "r'(?i)\\bDept\\b\\.?i\\'", 'ID': '18', 'Replacement': "'Department'"}
{'Pattern': "r'(?i)Califronia'", 'ID': '19', 'Replacement': "'California'"}
{'Pattern': "r'(?i)\\bJohn\\bHopkins\\b'", 'ID': '20', 'Replacement': "'Johns Hopkins'"}
{'Pattern': "r'(?i)\\bOrg\\b\\.?'", 'ID': '21', 'Replacement': "'Organization'"}
{'Pattern': "r'(?i)^[T]he\\s'", 'ID': '22', 'Replacement': "''"}
{'Pattern': "r'(?i)\\bAuth\\b\\.?'", 'ID': '23', 'Replacement': "'Authority'"}
{'Pattern': "r'.'", 'ID': '24', 'Replacement': "''"}
{'Pattern': "r','", 'ID': '25', 'Replacement': "''"}
{'Pattern': "r'(?i)\\s+'", 'ID': '0', 'Replacement': "''"}

以下是csv文件中的几行内容(在TextMate中打开)

0,r'(?i)\s+',''
1,r'(?i)&','and'
2,r'(?i)\bAssoc\b\.?','Association'
3,r'(?i)\bInc\b\.?','Inc.'

2 个回答

2

如果你把模式前面的 r'' 去掉,它就能正常工作了。

所以,匹配 . 的模式应该简单写成 '\.',而不是 "r'\.'"。

问题在于,你的模式中的 r 被当作一个普通的字母 r,而不是表示原始字符串的意思。

你也可以试试这个方法: v=re.sub(eval(row['Pattern']), row['Replacement'], v)

2

你的问题在于,你的模式值实际上并不是你想要的正则表达式模式,而是被额外的字符串包裹起来了。

举个例子,在你的字典里,你有一个值是 "r'.'",你把它当作模式来使用。你的代码会运行 re.sub("r'.'", "", v),这可能并不是你想要的结果:

>>> re.sub("r'.'", "", "This . won't match")
"This . won't match"
>>> re.sub("r'.'", "", "This r'x' will match")
'This  will match'

要解决这个问题,你应该回去看看你是怎么把正则表达式添加到字典里的,停止做那些导致字符串被包裹的操作。可能是像 row['Pattern'] = repr(regex) 这样的代码。

如果你出于某种原因需要保持字典不变,那么在使用 eval 时要非常小心。如果这些字符串来自不可信的来源,使用 eval 是一个很大的安全隐患。建议使用 ast.literal_eval 来替代。

撰写回答