Python : Splitting a string by numbers, letters and -_

Viewed 123

Let's say that I have a string like this one

string = 'rename_file_1122--23-_12'

Is there a way to split this like that

parts = ['rename','_','file','_','1122','--','23','-_','12']

I tried with the regular expression but it does not work

import re

name_parts = re.findall('\d+|\D+|\w+|\W+', string)

The result was:

['rename_file_', '1122', '--', '23', '-_', '12']

########## Second part

If I have a string like this one :

string2 = 'Hello_-Marco5__-'

What are the conditions that I need to use to get :['Hello','_-','Marco','5','__-']. My goal is to split a string y groups of letters,digits ans '-_'.

Thanks fors yours answers

3 Answers

You can use

re.findall(r'[^\W_]+|[\W_]+', string)

See the regex demo.

Regex details:

  • [^\W_]+ - one or more chars other than non-word and _ chars (so, one or more letters or digits)
  • | - or
  • [\W_]+ - one or more non-word and/or _ chars.

See a Python demo:

import re
string = 'rename_file_1122--23-_12'
name_parts = re.findall(r'[^\W_]+|[\W_]+', string)
print(name_parts)
# => ['rename', '_', 'file', '_', '1122', '--', '23', '-_', '12']

Alternatively you could use groupby from itertools:

from itertools import groupby

string = 'rename_file_1122--23-_12'

result = [''.join(value) for key, value in groupby(string, key=str.isalnum)]

print(result)

Output:

['rename', '_', 'file', '_', '1122', '--', '23', '-_', '12']

edit:

I came up with a perhaps simpler solution, using regular expressions:

string = 'rename_file_1122--23-_12'
result = re.split('([_-]*)', string)
print(result)

Same output.

re.split will split the string based upon matching the regular expression. The expression I've used includes a grouping pattern, and split includes the match in the result:

([_-]*)

Means match (and remember the result) of a sequence of one or more of any of _ or -. * means one or more, [] means any of whatever's inside the square brackets.

Without the group, just using [_-]* we'd get the following, without the matches:

string = 'rename_file_1122--23-_12'
result = re.split('[_-]*', string)
print(result)

Output:

['rename', 'file', '1122', '23', '12']

I have found the solution for the second part, it is the following :

name_parts=re.findall(r'[^\d_]+|[^\D]+|[^\W_]+|[\W_]+', string)
Related