使用Python我需要删除多行字符串中的所有字符,直到给定模式的第一次出现。在Perl中,这可以使用正则表达式来完成,例如:
#remove all chars up to first occurrence of cat or dog or rat
$pattern = 'cat|dog|rat'
$pagetext =~ s/(.*?)($pattern)/$2/xms;
在Python中使用它的最佳方法是什么?
答案 0 :(得分:5)
>>> import re
>>> s = 'hello cat!'
>>> m = re.search('cat|dog|rat', s)
>>> s[m.start():]
'cat!'
当然,您需要考虑真实解决方案中无法匹配的情况。
或者,更干净:
>>> import re
>>> s = 'hello cat!'
>>> p = 'cat|dog|rat'
>>> re.sub('.*?(?=%s)' % p, '', s, 1)
'cat!'
对于多线,请使用re.DOTALL
标记。
答案 1 :(得分:4)
您要删除模式的第一个出现之前的所有字符;例如,你给“猫|狗|老鼠”。
使用re
实现此目的的代码:
re.sub("(?s).*?(cat|dog|rat)", "\\1", input_text, 1)
或者,如果您将再次使用此正则表达式:
rex= re.compile("(?s).*?(cat|dog|rat)")
result= rex.sub("\\1", input_text, 1)
请注意非贪婪的.*?
。最初的(?s)
允许在匹配单词之前匹配换行符。
示例:
>>> input_text= "I have a dog and a cat"
>>> re.sub(".*?(cat|dog|rat)", "\\1", input_text, 1)
'dog and a cat'
>>> re.sub("(?s).*?(cat|dog|rat)", "\\1", input_text, 1)
'I have no animals!'
>>> input_text= "This is irrational"
>>> re.sub("(?s).*?(cat|dog|rat)", "\\1", input_text, 1)
'rational'
如果你想为单词 cat,dog和rat进行转换 ,你必须将正则表达式更改为:
>>> re.sub(r"(?s).*?\b(cat|dog|rat)\b", "\\1", input_text, 1)
'This is irrational'
答案 2 :(得分:2)
非正则表达方式
>>> s='hello cat!'
>>> pat=['cat','dog','rat']
>>> for n,i in enumerate(pat):
... m=s.find(i)
... if m != -1: print s[m:]
...
cat!
答案 3 :(得分:1)
这样的事情应该做你想做的事情:
import re
text = ' sdfda faf foo zing baz bar'
match = re.search('foo|bar', text)
if match:
print text[match.start():] # ==> 'foo zing baz bar'
答案 4 :(得分:0)
另一个选择是使用向前看s/.*?(?=$pattern)//xs
:
re.sub(r'(?s).*?(?=cat|dog|rat)', '', text, 1)
非正则表达方式:
for option in 'cat dog rat'.split():
index = text.find(option)
if index != -1: # found
text = text[index:]
break
非正则表达式几乎快5倍(对于某些输入):
$ python -mtimeit -s'from drop_until_word import drop_re, text, options;' \
> 'drop_re(text, options)'
1000 loops, best of 3: 1.06 msec per loop
$ python -mtimeit -s'from drop_until_word import drop_search, text, options;'\
> 'drop_search(text, options)'
10000 loops, best of 3: 184 usec per loop
$ python -mtimeit -s'from drop_until_word import drop_find, text, options;' \
> 'drop_find(text, options)'
1000 loops, best of 3: 207 usec per loop
drop_until_word.py
的位置:
import re
def drop_re(text, options):
return re.sub(r'(?s).*?(?='+'|'.join(map(re.escape, options))+')', '',
text, 1)
def drop_re2(text, options):
return re.sub(r'(?s).*?('+'|'.join(map(re.escape, options))+')', '\\1',
text, 1)
def drop_search(text, options):
m = re.search('|'.join(map(re.escape, options)), text)
return text[m.start():] if m else text
def drop_find(text, options):
indexes = [i for i in (text.find(option) for option in options) if i != -1]
return text[min(indexes):] if indexes else text
text = open('/usr/share/dict/words').read()
options = 'cat dog rat'.split()
def test():
assert drop_find(text, options) == drop_re(text, options) \
== drop_re2(text, options) == drop_search(text, options)
txt = 'dog before cat'
r = txt
for f in [drop_find, drop_re, drop_re2, drop_search]:
assert r == f(txt, options), f.__name__
if __name__=="__main__":
test()