使用re.findall()我已经设法返回字符串中的正则表达式的多个匹配.但是我返回的对象是字符串中的匹配列表.这不是我想要的.
我想要的是用其他东西替换所有匹配.我尝试使用类似于在re.sub中使用的类似语法来执行此操作:
import json
import re
regex = re.compile('([a-zA-Z]\"[a-zA-Z])', re.S)
filepath = "C:\\Python27\\Customer Stuff\\Austin Tweets.txt"
f = open(filepath, 'r')
myfile = re.findall(regex, '([a-zA-Z]\%[a-zA-Z])', f.read())
print myfile
Run Code Online (Sandbox Code Playgroud)
但是,这会产生以下错误:
Traceback (most recent call last):
File "C:/Python27/Customer Stuff/Austin's Script.py", line 9, in <module>
myfile = re.findall(regex, '([a-zA-Z]\%[a-zA-Z])', f.read())
File "C:\Python27\lib\re.py", line 177, in findall
return _compile(pattern, flags).findall(string)
File "C:\Python27\lib\re.py", line 229, in _compile
bypass_cache = flags & DEBUG
TypeError: unsupported operand type(s) for &: 'str' and 'int'
Run Code Online (Sandbox Code Playgroud)
任何人都可以帮助我在最后一点语法中我需要用原始Python对象中的其他东西替换所有匹配吗?
编辑:
根据收到的评论和答案,这里是我试图将一个正则表达式与另一个正则表达式:
import json
import re
regex = re.compile('([a-zA-Z]\"[a-zA-Z])', re.S)
regex2 = re.compile('([a-zA-Z]%[a-zA-Z])', re.S)
filepath = "C:\\Python27\\Customer Stuff\\Austin Tweets.txt"
f = open(filepath, 'r')
myfile = f.read()
myfile2 = re.sub(regex, regex2, myfile)
print myfile
Run Code Online (Sandbox Code Playgroud)
这会产生以下错误:
Traceback (most recent call last):
File "C:/Python27/Customer Stuff/Austin's Script.py", line 11, in <module>
myfile2 = re.sub(regex, regex2, myfile)
File "C:\Python27\lib\re.py", line 151, in sub
return _compile(pattern, flags).sub(repl, string, count)
File "C:\Python27\lib\re.py", line 273, in _subx
template = _compile_repl(template, pattern)
File "C:\Python27\lib\re.py", line 258, in _compile_repl
p = sre_parse.parse_template(repl, pattern)
File "C:\Python27\lib\sre_parse.py", line 706, in parse_template
s = Tokenizer(source)
File "C:\Python27\lib\sre_parse.py", line 181, in __init__
self.__next()
File "C:\Python27\lib\sre_parse.py", line 183, in __next
if self.index >= len(self.string):
TypeError: object of type '_sre.SRE_Pattern' has no len()
Run Code Online (Sandbox Code Playgroud)
Pad*_*ham 13
import re
regex = re.compile('([a-zA-Z]\"[a-zA-Z])', re.S)
myfile = 'foo"s bar'
myfile2 = regex.sub(lambda m: m.group().replace('"',"%",1), myfile)
print(myfile2)
Run Code Online (Sandbox Code Playgroud)
如果我正确理解了您的问题,那么您正在尝试用两个字符之间的百分号替换两个字符之间的引号。
有几种方法可以使用re.sub(re.findall根本不进行替换,因此您最初的尝试总是注定要失败)。
一种简单的方法是更改您的模式以分别对字母进行分组,然后使用包含反向引用的替换字符串:
pattern = re.compile('([a-zA-Z])\"([a-zA-Z])', re.S)
re.sub(pattern, r'\1%\2', text)
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用替换函数而不是替换字符串。对于match文本中找到的每个匹配项,将使用一个对象调用该函数,其返回值是替换:
pattern = re.compile('[a-zA-Z]\"[a-zA-Z]', re.S)
re.sub(pattern, lambda match: "{0}%{2}".format(*match.group()), text)
Run Code Online (Sandbox Code Playgroud)
(可能还有很多其他实现 lambda 函数的方法。我喜欢字符串格式。)
但是,最好的方法可能是在您的模式中使用前瞻和后视,以确保您的引号在字母之间而不实际匹配这些字母。这使您可以使用普通字符串'%'作为替换:
pattern = re.compile('(?<=[a-zA-Z])\"(?=[a-zA-Z])', re.S)
re.sub(pattern, '%', text)
Run Code Online (Sandbox Code Playgroud)
这确实与其他版本的语义略有不同。文本 like'a"b"c'将替换两个引号,而之前的代码只会替换第一个。希望这是一个改进!