web-dev-qa-db-fra.com

Le code produit ressemble à abcd2343, ce qui doit être divisé par des lettres et des chiffres

J'ai une liste de codes de produits dans un fichier texte, sur chaque comme est le code de produit qui ressemble à:

abcd2343 abw34324 abc3243-23A

Il s'agit donc de lettres suivis de chiffres et autres caractères.

Je veux split sur le première occurrence d'un nombre.

30
Blankman
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']

Ou, si vous souhaitez diviser la première occurrence d'un chiffre:

In [43]: re.findall('\d*\D+',s)
Out[43]: ['abcd', '2343 abw', '34324 abc', '3243-', '23A']

  • \d+ Correspond à 1 ou plusieurs chiffres.
  • \d*\D+ Correspond à 0 ou plusieurs chiffres suivis de 1 ou plusieurs non-chiffres.
  • \d+|\D+ Correspond à 1 ou plusieurs chiffres ou 1 ou plusieurs non-chiffres.

Consultez la documentation pour en savoir plus sur la syntaxe des expressions rationnelles de Python.


re.split(pat, s) divisera la chaîne s en utilisant pat comme délimiteur. Si pat commence et se termine par des parenthèses (afin d'être un "groupe de capture"), alors re.split Renverra également les sous-chaînes correspondant à pat. Par exemple, comparez:

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

En revanche, re.findall(pat, s) renvoie uniquement les parties de s qui correspondent à pat:

In [115]: re.findall('\d+', s)
Out[115]: ['2343', '34324', '3243', '23']

Ainsi, si s se termine par un chiffre, vous pouvez éviter de terminer par une chaîne vide en utilisant re.findall('\d+|\D+', s) au lieu de 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']
42
unutbu
import re

m = re.match(r"(?P<letters>[a-zA-Z]+)(?P<the_rest>.+)$",input)

m.group('letters')
m.group('the_rest')

Cela couvre votre cas d'angle abc3243-23A et produira abc pour le groupe de lettres et 3243-23A pour the_rest

Puisque vous avez dit qu'ils sont tous sur des lignes individuelles, vous devrez évidemment mettre une ligne à la fois dans input

1
jwsample

Pour partitionner sur le premier chiffre

parts = re.split('(\d.*)','abcd2343')      # => ['abcd', '2343', '']
parts = re.split('(\d.*)','abc3243-23A')   # => ['abc', '3243-23A', '']

Ainsi, les deux parties sont toujours des parties [0] et des parties [1].

Bien sûr, vous pouvez l'appliquer à plusieurs codes:

>>> s = "abcd2343 abw34324 abc3243-23A"
>>> results = [re.split('(\d.*)', pcode) for pcode in s.split(' ')]
>>> results
[['abcd', '2343', ''], ['abw', '34324', ''], ['abc', '3243-23A', '']]

Si chaque code est sur une ligne individuelle, au lieu de s.split( ) utilisez s.splitlines().

1
Muhammad Alkarouri

Essayez ce code, cela fonctionnera bien

import re
text = "MARIA APARECIDA 99223-2000 / 98450-8026"
parts = re.split(r' (?=\d)',text, 1)
print(parts)

Production:

["MARIA APARECIDA", "99223-2000/98450-8026"]

0
Basant Rules
def firstIntIndex(string):
    result = -1
    for k in range(0, len(string)):
        if (bool(re.match('\d', string[k]))):
            result = k
            break
    return result
0
Mike