基本上我想编写一个清理URL的脚本,用"(点)"替换点。串。 例如,如果我在运行脚本后有http://www.google.com,我希望它是http://www(dot)google(dot)。 当我的文本文件只包含网址或其他字符串时,这很容易用.replace实现,但在我的情况下,我的文本文件中也有IP地址,我不希望IP地址中的点更改为& #34;(点)"
我尝试使用正则表达式执行此操作,但我的输出是 " http://ww(dot)oogl(dot)om 192.60.10.10 33.44.55.66"
这是我的代码
from __future__ import print_function
import sys
import re
nargs = len(sys.argv)
if nargs < 2:
sys.exit('You did not specify a file')
else:
inputFile = sys.argv[1]
fp = open(inputFile)
content = fp.read()
replace = '(dot)'
regex = '[a-z](\.)[a-z]'
print(re.sub(regex, replace, content, re.M| re.I| re.DOTALL))
我想我需要有一个条件来检查模式是否为number.number - 不要替换。
答案 0 :(得分:3)
您可以使用前瞻和后瞻断言:
import re
s = "http://www.google.com 127.0.0.1"
print(re.sub("(?<=[a-z])\.(?=[a-z])", "(dot)", s))
http://www(dot)google(dot)com 127.0.0.1
要为字母和数字工作,这应该可以做到这一点,确保至少有一个字母:
s = "http://www.googl1.2com 127.0.0.1"
print(re.sub("(?=.*[a-z])(?<=\w)\.(?=\w)", "(dot)", s, re.I))
http://www(dot)googl1(dot)2com 127.0.0.1
对于您的文件,您需要re.M
:
In [1]: cat test.txt
google8.com
google9.com
192.60.10.10
33.44.55.66
google10.com
192.168.1.1
google11.com
In [2]: with open("test.txt") as f:
...: import re
...: print(re.sub("(?=.*[a-z])(?<=\w)\.(?=\w)", "(dot)", f.read(), re.I|re.M))
...:
google8(dot)com
google9(dot)com
192.60.10.10
33.44.55.66
google10(dot)com
192.168.1.1
google11(dot)com
如果文件很大且内存有问题,你也可以逐行进行,要么将所有行存储在列表中,要么随时使用每一行:
import re
with open("test.txt") as f:
r = re.compile("(?=.*[a-z])(?<=\w)\.(?=\w)", re.I)
lines = [r.sub("(?=.*[a-z])(?<=\w)\.(?=\w)", "(dot)") for line in f]
答案 1 :(得分:1)
根据您的代码判断,您希望替换模式中的第一个组。但是,re.sub
会替换整个匹配模式,而不是组。在你的情况下,这是在句号之前的单个字符,句点本身和在它之后的单个字符。
即使子工作符合您的期望,您的正则表达式也会缺少数字是URL的一部分的边缘情况,例如www.2048game.com
。
定义IP看起来更容易。它总是一组四个数字,每个数字有一个,两个或三个数字,用点分隔。 (无论如何,在IPv4的情况下。但IPv6不使用句点,所以这里没关系。)
假设您的文本文件中只有URL和IP,只需过滤掉所有IP,然后替换剩余URL中的句点:
is_ip = re.compile('\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}')
urls = content.split(" ")
for i, url in enumerate(urls):
if not is_ip.match(url):
urls[i] = url.replace('.', '(dot)')
content = ' '.join(urls)
当然,如果您在content
中有常规文字,这也会替换所有常规时段,而不仅仅是网址。在这种情况下,您首先需要更复杂的URL检测。见In search of the perfect URL validation regex
答案 2 :(得分:0)
您必须在点之前和之后存储[a-z]
内容,以便将其再次放入替换后的字符串中。我在这里解决了这个问题:
from __future__ import print_function
import sys
import re
nargs = len(sys.argv)
if nargs < 2:
sys.exit('You did not specify a file')
else:
inputFile = sys.argv[1]
fp = open(inputFile)
content = fp.read()
replace = '\\1(dot)\\3'
regex = '(.*[a-z])(\.)([a-z].*)'
print(re.sub(regex, replace, content, re.M| re.I| re.DOTALL))
答案 3 :(得分:0)
import re
content = "I tried to do this using regex, but my output is http://www.googl.com 192.60.10.10 33.44.55.66\nhttp://ya.ru\n..."
reg = r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+'
all_urls = re.findall(reg, content, re.M| re.I| re.DOTALL)
repl_urls = [u.replace('.', '(dot)') for u in all_urls]
for u, r in zip(all_urls, repl_urls):
content = content.replace(u, r)
print content