如何让所有字符都变成一个数字?
How to get all characters upto a number?
我有如下字符串
>>> 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
为例,用 dash 或 underbar 或 dot 作为分隔符分割后, 123
将是 all number
( isdigit),所以得到 this_is-a123.456string-
之前的所有内容,所以如果输入字符串是 this_1s-a-4.test
,输出应该是 this_1s-a-
,因为 4 是拆分后的全数。
不确定它是否适用于所有情况,但您可以尝试:
for a in re.split('-|_|\.',s2).reverse():
if a.isdigit():
r=re.rsplit(a,s2)[0]
break
print(r)
这将适用于您的示例案例:
def fn(s):
return re.match("(.*?[-_.]|^)\d+([-_.]|$)", s).group(1)
(^
和$
分别匹配字符串的开头和结尾,.*?
中的?
进行非贪婪匹配。)
更多案例:
>>> fn("111")
""
>>> fn(".111")
"."
>>> fn(".1.11")
"."
你可能还想想想如果没有全数组你想得到什么:
>>> fn("foobar")
这适用于您的示例
代码
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.']
我有如下字符串
>>> 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
为例,用 dash 或 underbar 或 dot 作为分隔符分割后, 123
将是 all number
( isdigit),所以得到 this_is-a123.456string-
之前的所有内容,所以如果输入字符串是 this_1s-a-4.test
,输出应该是 this_1s-a-
,因为 4 是拆分后的全数。
不确定它是否适用于所有情况,但您可以尝试:
for a in re.split('-|_|\.',s2).reverse():
if a.isdigit():
r=re.rsplit(a,s2)[0]
break
print(r)
这将适用于您的示例案例:
def fn(s):
return re.match("(.*?[-_.]|^)\d+([-_.]|$)", s).group(1)
(^
和$
分别匹配字符串的开头和结尾,.*?
中的?
进行非贪婪匹配。)
更多案例:
>>> fn("111")
""
>>> fn(".111")
"."
>>> fn(".1.11")
"."
你可能还想想想如果没有全数组你想得到什么:
>>> fn("foobar")
这适用于您的示例
代码
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.']