Mam problem w Pythonie, tworząc regex, aby uzyskać każde wystąpienie, które pasuje do regexa. Mam ten kod, który wykonałem, że potrzebuję pomocy.

strToSearch= "1A851B 1C331 1A3X1 1N111 1A3 and a whole lot of random other words."
print(re.findall('\d{1}[A-Z]{1}\d{3}', strToSearch.upper())) #1C331, 1N111
print(re.findall('\d{1}[A-Z]{1}\d{1}[X]\d{1}', strToSearch.upper())) #1A3X1
print(re.findall('\d{1}[A-Z]{1}\d{3}[A-Z]{1}', strToSearch.upper())) #1A851B
print(re.findall('\d{1}[A-Z]{1}\d{1}', strToSearch.upper())) #1A3

>['1A851', '1C331', '1N111']
>['1A3X1']
>['1A851B']
>['1A8', '1C3', '1A3', '1N1', '1A3']

Jak widać, zwraca "1A851" w pierwszym, którego tego nie chcę. Jak trzymaj go przed pokazaniem w pierwszym wygenerze? Niektóre rzeczy, które wiesz, to może pojawić się w sznurku jak "Słowa słowa 1A851b?" Muszę więc zachować interpunkcję od chwytania.

Również jak mogę połączyć je w jeden Regex. Zasadniczo moim celem końcowym jest uruchomienie oświadczenia IF w Pythonie podobnym do poniższego kodu Pseudo.

lstResults = []
strToSearch= " Alot of 1N1X1 people like to eat 3C191 cheese and I'm a 1A831B aka 1A8."
lstResults = re.findall('<REGEX HERE>', strToSearch)
for r in lstResults:
    print(r)

I pożądane wyjście byłoby

1N1X1
3C191 
1A831B
1A8
-2
MatthewEnderle 25 czerwiec 2017, 12:03

3 odpowiedzi

Najlepsza odpowiedź

W przypadku wzoru Single Regex :

strToSearch= " Alot of 1N1X1 people like to eat 3C191 cheese and I'm a 1A831B aka 1A8."
lstResults = [i[0] for i in re.findall(r'(\d[A-Z]\d{1,3}(X\d|[A-Z])?)', strToSearch)]

print(lstResults)

Wyjście:

['1N1X1', '3C191', '1A831B', '1A8']
0
RomanPerekhrest 25 czerwiec 2017, 09:20

Jeśli chcesz znaleźć "Słowa", gdzie są oboje cyfry, a litery mieszano, najłatwiej jest użyć operatora buntowego słowa, \b; Ale zauważ, że musisz użyć r'' ciągów / uciekaj \ w kodzie (który musisz zrobić dla \d w przyszłości w przyszłych wersjach Python). Aby dopasować dowolną sekwencję znaków alfanumerycznych oddzielonych granicami Word, można użyć

r'\b[0-9A-Z]+\b'

Jednak nie gwarantuje to jeszcze, że jest co najmniej jedna liczba i przynajmniej jedna litera. W tym celu użyjemy pozytywnej zerowej szerokości Lookhead Asertion (?= ), co oznacza, że całe mecze REGEX tylko wtedy, gdy zawarte dopasowania wzoru w tym momencie. Potrzebujemy ich z nich: jeden zapewnia co najmniej jedną cyfrę i jeden, że jest co najmniej jedna litera:

>>> p = r'\b(?=[0-9A-Z]*[0-9])(?=[0-9A-Z]*[A-Z])[0-9A-Z]+\b'
>>> re.findall(p, '1A A1 32 AA 1A123B')
['1A', 'A1', '1A123B']

Spowoduje to teraz dopasowanie wszystkiego, w tym 33333A lub AAAAAAAAAA3A tak długo, jak jest co najmniej jedna cyfra i jedna litera. Jeśli jednak wzór zawsze zacznie się od cyfry i zawsze zawierać list, staje się nieco łatwiejszy, na przykład:

>>> p = r'\b\d+[A-Z][0-9A-Z]*\b'
>>> re.findall(p, '1A A1 32 AA 1A123B')
['1A', '1A123B']

I.E. A1 nie pasował, ponieważ nie zaczyna się od cyfry.

0
Antti Haapala 25 czerwiec 2017, 09:32

Możesz użyć granic Word:

\b\d{1}[A-Z]{1}\d{3}\b

Zobacz Demo

W przypadku kombinacji jest niejasne kryterium, zgodnie z którym uważasz słowo "losowe słowo", ale możesz użyć czegoś takiego:

[A-Z\d]*\d[A-Z\d]*[A-Z][A-Z\d]*

To jest słowo zawierające co najmniej cyfrę i przynajmniej postać niecyfrową. Zobacz Demo.

A może możesz użyć:

\b\d[A-Z\d]*[A-Z][A-Z\d]*

Dor słowo, które zaczyna się od cyfry i zawiera przynajmniej niecyfrowej postaci. Zobacz Demo.

Lub jeśli chcesz połączyć dokładnie te regex, użyj.

\b\d[A-Z]\d(X\d|\d{2}[A-Z]?)?\b

Zobacz final Demo.

0
horcrux 25 czerwiec 2017, 09:23