从字符串中删除重复出现的(重叠的)斜杠

Remove recurrent (overlapping) slashes from string

我正在像这样解析 URLS

>>> from urllib.parse import urlparse
>>> urlparse('http://foo.bar/path/to/heaven')
ParseResult(scheme='http', netloc='foo.bar', path='/path/to/heaven', params='', query='', fragment='')

假设我有一个 URL 有一个格式错误的路径,循环 / 像这样:

>>> x = urlparse('http://foo.bar/path/to/////foo///baz//bar'))
ParseResult(scheme='http', netloc='foo.bar', path='/path/to/////foo///baz//bar', params='', query='', fragment='')

如您所见,x.path 仍然包含重复出现的斜线,我正在尝试删除它们,所以我尝试像这样拆分、循环和替换:

>>> newpath = x.path.split('/')
['', 'path', 'to', '', '', '', '', 'foo', '', '', 'baz', '', 'bar']
>>> for i in newpath:
    if i == '':
        newpath.remove('')
>>> '/'.join(newpath)
'/path/to/foo/baz/bar'

这提供了所需的输出,但我认为此解决方案效率低下而且很垃圾。我怎样才能做得更好?

这就是正则表达式的用途:

import regex as re

url = "http://foo.bar/path/to/////foo///baz//bar"

rx = re.compile(r'(?:(?:http|ftp)s?://)(*SKIP)(*FAIL)|/+')
url = rx.sub('/', url)
print(url)

这会产生

http://foo.bar/path/to/foo/baz/bar

参见 a demo on regex101.com。唯一真正的问题是在协议中保留任何双正斜杠,因此更新的 regex 模块和 (*SKIP)(*FAIL)。您可以在 re 模块中使用 lookbehinds 实现相同的功能。

import re

s = 'http://foo.bar/path/to/////foo///baz//bar'

s = re.sub(r'(?<!:)/{2,}', '/', s)
print(s)

打印:

http://foo.bar/path/to/foo/baz/bar

编辑:编译正则表达式:

import re

s = 'http://foo.bar/path/to/////foo///baz//bar'
r = re.compile(r'(?<!:)/{2,}')

s = r.sub('/', s)
print(s)

您不应修改正在迭代的列表。参见 strange result when removing item from a list

您可以使用列表理解来创建没有所有 '' 元素的列表。

newpath = [s in x.path.split('/') if s != '']
'/'.join(newpath)