我有一个字符串,每个字符由一个竖线字符(包括"|"
s本身)分隔,例如:
"f|u|n|n|y||b|o|y||a||c|a|t"
我想替换所有不在"|"
旁边的所有"|"
,以获得结果:
"funny|boy|a|cat"
我尝试使用mytext.replace("|", "")
,但这会删除所有内容并生成一个长字。
答案 0 :(得分:30)
这可以通过相对简单的正则表达式实现,而无需链str.replace
:
>>> import re
>>> s = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> re.sub('\|(?!\|)' , '', s)
'funny|boy|a|cat'
说明:\ |(?!\ |)将查找|
字符,后面没有其他|
个字符。 (?!foo)表示负向前瞻,确保你所匹配的任何东西都没有被foo跟随。
答案 1 :(得分:28)
使用哨兵值
将||
替换为~
。这将记住||
。然后删除|
。最后用|
重新替换它们。
>>> s = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> s.replace('||','~').replace('|','').replace('~','|')
'funny|boy|a|cat'
另一种更好的方法是使用它们几乎是替代文本的事实。解决方案是让它们完全交替......
s.replace('||','|||')[::2]
答案 2 :(得分:24)
您可以先用其他东西替换双管,以确保在移除单个管道后仍能识别它们。然后你将它们换回管道:
>>> t = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> t.replace('||', '|-|').replace('|', '').replace('-', '|')
'funny|boy|a|cat'
您应该尝试选择一个安全临时值的替换值,并且不会自然地出现在您的文本中。否则,即使它最初不是双管,您也会遇到替换该字符的冲突。因此,如果您的文字可能包含短划线,请不要使用上述短划线。您也可以同时使用多个字符,例如:'<THIS IS A TEMPORARY PIPE>'
。
如果你想完全避免这种冲突,你也可以解决这个问题。例如,您可以先通过双管道拆分字符串,然后对每个子字符串执行替换,最终将它们重新连接在一起:
>>> '|'.join([s.replace('|', '') for s in t.split('||')])
'funny|boy|a|cat'
当然,您也可以使用正则表达式来替换那些未被其他管道跟随的管道:
>>> import re
>>> re.sub('\|(?!\|)', '', t)
'funny|boy|a|cat'
答案 3 :(得分:11)
您可以使用positive look ahead正则表达式替换后跟字母字符的点数:
>>> import re
>>> st = "f|u|n|n|y||b|o|y||a||c|a|t"
>>> re.sub(r'\|(?=[a-z]|$)',r'',st)
'funny|boy|a|cat'
答案 4 :(得分:6)
使用正则表达式。
import re
line = "f|u|n|n|y||b|o|y||a||c|a|t"
line = re.sub("(?!\|\|)(\|)", "", line)
print(line)
输出:
funny|boy|a|cat
答案 5 :(得分:6)
捕获组的另一个正则表达式选项。
>>> import re
>>> re.sub(r'\|(\|?)', r'\1', "f|u|n|n|y||b|o|y||a||c|a|t")
'funny|boy|a|cat'
<强>解释强>
\|
- 匹配所有管道字符。
(\|?)
- 捕获以下管道字符(如果存在)。然后用\1
替换匹配将为您带来第一个捕获组的内容。因此,在单个pip的位置,它将给出一个空字符串,在||
中,它将带来第二个管道字符。
通过单词和非单词边界的另一个技巧......
>>> re.sub(r'\b\|\b|\b\|\B', '', "f|u|n|n|y||b|o|y||a||c|a|t|")
'funny|boy|a|cat'
还有一个使用负面看法......
>>> re.sub(r'(?<!\|)\|', '', "f|u|n|n|y||b|o|y||a||c|a|t|")
'funny|boy|a|cat'
...奖金
>>> re.sub(r'\|(\|)|\|', lambda m: m.group(1) if m.group(1) else '', "f|u|n|n|y||b|o|y||a||c|a|t")
'funny|boy|a|cat'
答案 6 :(得分:4)
如果您打算使用正则表达式,最快的方法是拆分和加入:
In [18]: r = re.compile("\|(?!\|)")
In [19]: timeit "".join(r.split(s))
100000 loops, best of 3: 2.65 µs per loop
In [20]: "".join(r.split(s))
Out[20]: 'funny|boy|a|cat'
In [30]: r1 = re.compile('\|(?!\|)')
In [31]: timeit r1.sub("", s)
100000 loops, best of 3: 3.20 µs per loop
In [33]: r2 = re.compile("(?!\|\|)(\|)")
In [34]: timeit r2.sub("",s)
100000 loops, best of 3: 3.96 µs per loop
str.split
和str.replace
方法仍然更快:
In [38]: timeit '|'.join([ch.replace('|', '') for ch in s.split('||')])
The slowest run took 11.18 times longer than the fastest. This could mean that an intermediate result is being cached
100000 loops, best of 3: 1.71 µs per loop
In [39]: timeit s.replace('||','|||')[::2]
1000000 loops, best of 3: 536 ns per loop
In [40]: timeit s.replace('||','~').replace('|','').replace('~','|')
1000000 loops, best of 3: 881 ns per loop
取决于字符串中的内容将决定str.replace
方法,但无论字符串中包含哪些字符,str.split
方法都将起作用。