我需要对字符串中与正则表达式不匹配的部分进行url编码。目前的解决方案(如下(是:
- 选择我匹配的正则表达式(###.*##(
- 将找到的子字符串放在列表中,并用一些不可编码的索引替换它们~~1~~
- 对所有内容进行编码(整个url(
- 把我找到的元素放回去
我有这个代码可以工作。但我相信它可以做得更好,只需一次解析就可以查找与正则表达式不匹配的字符串部分。每次这样做都会增加巨大的开销。
import re
from itertools import count
import urllib.parse
def replace_parts(url):
parts = []
counter = count(0)
def replace_to(match):
match = match.group(0)
parts.append(match)
return '~~' + str(next(counter)) + '~~'
def replace_from(match):
return parts[next(counter)]
url = re.sub(r'##(.*?)##', replace_to, url)
url = urllib.parse.quote(url)
counter = count(0)
url = re.sub(r'~~([0-9]+)~~', replace_from, url)
print (url)
url1 = "http://google.com?this_is_my_encodedurl##somethin##&email=##other##tr"
url = replace_parts(url1)
# this becomes http%3A%2F%2Fgoogle.com%3Fthis_is_my_encodedurl##somethin##%0A%26email%3D##other##tr
您可以使用re.sub
来匹配##.*?##
模式,也可以使用它前面的文本,这样您就可以将两类文本作为一对。然后只在回调函数的第一部分应用URL编码。为了处理输入的结束,允许第二部分是##.*?##
模式或输入的结束($
(:
def replace_parts(url):
return re.sub(r'(.*?)(##.*?##|$)',
lambda m: urllib.parse.quote(m[1]) + m[2],
url)
另一个使用re.sub和lambda的选项,使用捕获组和带有交替的匹配。
在lambda中,检查捕获组1是否存在。如果是,则应用urllib.parse.quot
,然后返回。如果没有组1,则返回匹配项。
有关匹配项和组,请参阅regex演示。
图案与匹配
##S*?##
在##|
或((?:(?!##.*?##)S)+)
在组1中捕获不直接跟在##...##
后面的字符序列
示例
import re
import urllib.parse
pattern = r"##S*?##|((?:(?!##.*?##)S)+)"
def replace_parts(url):
return re.sub(
pattern,
lambda m: urllib.parse.quote(m[1]) if m[1] else m[0],
url
)
s = "http://google.com?this_is_my_encodedurl##somethin##&email=##other##tr"
print(replace_parts(s))
输出
http%3A//google.com%3Fthis_is_my_encodedurl##somethin##%26email%3D##other##tr