我在一个文本文件中有一个产品代码列表,每个产品代码都是如下产品代码:
abcd2343 abw34324 abc3243-23A
所以是字母后跟数字和其他字符.
我想分开第一次出现的数字.
unu*_*tbu 47
In [32]: import re
In [33]: s='abcd2343 abw34324 abc3243-23A'
In [34]: re.split('(\d+)',s)
Out[34]: ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A']
Run Code Online (Sandbox Code Playgroud)
或者,如果要在第一次出现的数字时拆分:
In [43]: re.findall('\d*\D+',s)
Out[43]: ['abcd', '2343 abw', '34324 abc', '3243-', '23A']
Run Code Online (Sandbox Code Playgroud)
\d+ 匹配1位或更多位数.\d*\D+ 匹配0或更多数字后跟1或更多非数字.\d+|\D+匹配1位或更多位数或 1 位或更多位非数字.有关Python的正则表达式语法的更多信息,请参阅文档.
re.split(pat, s)将s使用pat分隔符拆分字符串.如果pat以括号开头和结尾(以便成为"捕获组"),那么re.split也将返回匹配的子串pat.例如,比较:
In [113]: re.split('\d+', s)
Out[113]: ['abcd', ' abw', ' abc', '-', 'A'] # <-- just the non-matching parts
In [114]: re.split('(\d+)', s)
Out[114]: ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A'] # <-- both the non-matching parts and the captured groups
Run Code Online (Sandbox Code Playgroud)
相反,re.findall(pat, s)只返回s匹配的部分pat:
In [115]: re.findall('\d+', s)
Out[115]: ['2343', '34324', '3243', '23']
Run Code Online (Sandbox Code Playgroud)
因此,如果s以数字结尾,则可以避免以空字符串结尾,re.findall('\d+|\D+', s)而不是使用re.split('(\d+)', s):
In [118]: s='abcd2343 abw34324 abc3243-23A 123'
In [119]: re.split('(\d+)', s)
Out[119]: ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A ', '123', '']
In [120]: re.findall('\d+|\D+', s)
Out[120]: ['abcd', '2343', ' abw', '34324', ' abc', '3243', '-', '23', 'A ', '123']
Run Code Online (Sandbox Code Playgroud)
该函数还处理浮点数和负数。
def separate_number_chars(s):
res = re.split('([-+]?\d+\.\d+)|([-+]?\d+)', s.strip())
res_f = [r.strip() for r in res if r is not None and r.strip() != '']
return res_f
Run Code Online (Sandbox Code Playgroud)
例如:
utils.separate_number_chars('-12.1grams')
> ['-12.1', 'grams']
Run Code Online (Sandbox Code Playgroud)