>我有如下字符串
>>> s1
'this_is-a.string-123-with.number'
>>> s2
'this_is-a123.456string-123-with.number'
>>> s3
'one-0more-str.999'
拆分后需要获取所有数字(不是字母数字)之前的所有内容,因此从s1
中获取this_is-a.string-
,从 S2 获取this_is-a123.456string-
,从 S3 获取one-0more-str.
。
>>> for a in re.split('-|_|.',s2):
... if a.isdigit():
... r=re.split(a,s2)[0]
... break
>>> print(r)
# expected: this_is-a123.456string-
# got: this_is-a
上面的代码适用于 s1,但不适用于 s2,因为123
与 s2 中的a123
匹配,应该有更好的 pythonic 方法吗?
更多信息:
举s3
例子,当我们用-
或_
或.
作为分隔符进行拆分时,999 是我们唯一得到的所有数字,所以在此之前的所有内容都是one-0more-str.
需要打印的,如果我们以s2
为例,在用破折号或下划线或点作为分隔符拆分后,123
将是all number
(isdigit),所以在this_is-a123.456string-
之前获取所有内容,所以如果输入字符串要this_1s-a-4.test
,输出应该是this_1s-a-
,因为4是分裂后的全数。
这将适用于您的示例案例:
def fn(s):
return re.match("(.*?[-_.]|^)d+([-_.]|$)", s).group(1)
(^
和$
分别匹配字符串的开头和结尾,.*?
中的?
执行非贪婪匹配。
更多情况:
>>> fn("111")
""
>>> fn(".111")
"."
>>> fn(".1.11")
"."
您可能还需要考虑如果没有所有数字的组,您想要获得什么:
>>> fn("foobar")
不确定它是否适用于所有情况,但您可以尝试:
for a in re.split('-|_|.',s2).reverse():
if a.isdigit():
r=re.rsplit(a,s2)[0]
break
print(r)
这适用于您的示例
法典
def parse(s):
""" Splits on successive digits,
then takes everything up to last split on digits """
return ''.join(re.split(r'(d+)', s)[:-2])
测试
使用指定的字符串
for t in ['this_is-a.string-123-with.number',
'this_is-a123.456string-123-with.number',
'one-0more-str.999']:
print(f'{parse(t)}')
输出
this_is-a.string-
this_is-a123.456string-
one-0more-str.
解释
字符串
s = 'this_is-a123.456string-123-with.number'
拆分为一组数字
re.split(r'(d+)', s)
Out: ['this_is-a', '123', '.', '456', 'string-', '123', '-with.number']
省略拆分的最后两个项目
re.split(r'(d+)', s)[:-2] # [:-2] slice dropping last two items of list
Out: ['this_is-a', '123', '.', '456', 'string-']
将列表联接到字符串中
''.join(re.split(r'(d+)', s)[:-2]) # join items
Out: this_is-a123.456string-
如果我正确理解了你想要什么,你可以使用一个正则表达式来获取你需要的值:
import re
s1='this_is-a.string-123-with.number'
s2='this_is-a123.456string-123-with.number'
s3='one-0more-str.999'
# matches any group that is in between "all numbers"...
regex = re.compile('(.*[-._])d+([-._].*)?')
m = regex.match(s1)
print(m.groups())
m = regex.match(s2)
print(m.groups())
m = regex.match(s3)
print(m.groups())
运行此命令时,结果如下:
('this_is-a.string-', '-with.number')
('this_is-a123.456string-', '-with.number')
('one-0more-str.', None)
如果您只对第一组感兴趣,则只能使用:
>>> print(m.group(1))
one-0more-str.
如果要筛选没有第二个组的情况:
>>> print([i for i in m.groups() if i])
['one-0more-str.']