Expected string or buffer (in re.sub)

2020-03-23 17:40发布

I have seen similar questions (here, here) before on SO and I know that re.sub expects a string (which, I believe, I am providing) but I don't know what's wrong in the following code:

tuples = re.findall(r'id":"(.*?)".*?name":"(.*?)"', response.text, re.DOTALL)
outfile = open("badEXtsWithIDs.csv", "wb")
print "Writing into CSV"
writer = csv.writer(outfile)
for entry in tuples:
    writeName = re.sub(r'\W', " ", entry)
    writer.writerow(writeName)

I think that re.sub needs a str variable but, isn't entry a str? I get a error: TypeError: expected string or buffer on the line havingre.sub. Any help appreciated.

标签: python
1条回答
▲ chillily
2楼-- · 2020-03-23 18:07

When you have more than one matching group, re.findall returns a list of n-tuples:

re.findall('(foo).(bar)', 'foo foo bar foo|bar')
Out[5]: [('foo', 'bar'), ('foo', 'bar')]

So clearly each entry in tuples is a tuple. When you pass a tuple to re.sub, well, it complains.

tuples = re.findall('(foo).(bar)', 'foo foo bar foo|bar')

for entry in tuples:
    re.sub('oo','ox',entry)

...
/usr/lib/python3.3/re.py in sub(pattern, repl, string, count, flags)
    168     a callable, it's passed the match object and must return
    169     a replacement string to be used."""
--> 170     return _compile(pattern, flags).sub(repl, string, count)
    171 
    172 def subn(pattern, repl, string, count=0, flags=0):

TypeError: expected string or buffer

So, do something else. Maybe use map:

for entry in tuples:
    print(' '.join(map(lambda s: re.sub('oo','ox',s),entry)))

fox bar
fox bar

Or more readably a comprehension

writer.writerow([re.sub(r'\W', " ",s) for s in entry])

etc.

查看更多
登录 后发表回答