Jak za pomocą wyrażeń regularnych wyszukać linijki zwierające dwie liczby?

0

Programuje w pythonie właściwie od dzisiaj... Mam taki problem. Docelowo mam sprawdzić czy w ppliku w kolejnych linijkach są kody pocztowe. Napisałam wzorzec, sądziłam że coś źle tam piszę i zeszłam tylko do sprawdzenia czy są dwie liczby:

import linecache
import re
i=1
wzorzec= r'[0-9]{2}'
while 1 :
	linijka= linecache.getline('text.txt',i)
	nowa_linijka=linijka.replace('\n','')
	print  str(len(nowa_linijka))
	i=i+1
	dopasowanie = re.search(nowa_linijka, wzorzec)
	if dopasowanie: 
		print 'TRUE' +" " + str(i-1)
	else:
		print 'FALSE'
	if not linijka : break

Pokazuję mi False mimo że są w niektórych linijkach dwie liczby przykładowo 23. Napisałam podobny program aby pobrać od użytkownika liczbę, i sprawdzić czy to liczba podobny efekt...

import re
wzorzec= r'[0-9]{2}'
kod_pocztowy=raw_input()
dopasowanie = re.search(kod_pocztowy, wzorzec)
if dopasowanie: 
	print 'TRUE' 
else:
	print 'FALSE'

Dla pliku pokazuję TRUE gdy linijka jest pusta o dziwo...

Co powinnam zmienić?

0

W Pythonie piszę tylko proste wtyczki do XBMC i słabo znam ten język, ale jest coś takiego jak re.compile z parametrem re.S dla wyłuskania tekstu wielolinijkowego.

Ale jeżeli chodzi tylko o sprawdzenie czy są dwie linijki z kodem pocztowym po sobie, to czy raczej wyrażenie nie powinno być takie?

^[0-9]{2}\-[0-9]{3}\n^[0-9]{2}\-[0-9]{3}\n
0

Biorę linijka po linijce i sprawdzam. Na początku napisałam podobne wyrażenie do Twojego. Przed '-' nie dałam '' więc dziękuję bo poprawiłeś jakby mój przyszły kod. Pobieram linijka po linijce więc sprawdzam czy raz wystąpiła taka sekwencja.

Problem polega na tym, że nawet dla wzorca który ma w sobie tylko jedną liczbę czyli [0-9], wyszukanie jest błędne pokazuje że nie ma mimo że jest. Działa dla liter i ciągów liter przykładowo dla A, ale gdy wpiszę (A){2} to też odmawia posłuszeństwa w sytuacjach gdy podane wyrażenie jest prawdziwe.

1

Wtrącę swoje trzy grosze w temacie "czystego" regexa.
Może lepsze będzie .*\d.*? \d to skrót dla [0-9]. Polecam www.regular-expressions.info/ i https://www.debuggex.com/.

(A) to grupa, tymczasem {2} powtarza nie grupę, a literę. Powinno zadziałać A{2}.
Dla dopasowania dwóch kodów pocztowych powinno zadziałać coś takiego: .*?\d\d-\d{3}.*?\d\d-\d{3}.*, złapie pierwsze dwa kody, o ile są obecne w linijce.

0

Właśnie ogólnie dla liczb nie działa, też próbowałam z tym d. Dla pewności wpisałam to co Ty. Przy 121212 Powinno być true bo mamy jakieś znaki liczbę i jakieś znaki... Nie? Nie wiem czemu to w ten sposób działa, może trzeba coś dołączyć aby obsługiwało liczby? (Chociaż to według mnie głupie)

Co do A, nadal jest tak samo.

Dla jednego A mimo że wymagam dwóch A, wypisuje true...

0

@lightinside escapeowanie poprzez \ znaków mogących określać zasady wyrażenia jest konieczne bo tutaj masz mieć fizycznie myślnik, a nie w rozumieniu ustalania zakresu znaków. Poza tym samo podanie zakresu znaków nic Ci nie da. Jeżeli się nie mylę należy określić długość chočby poprzez znak + za nawiasami kwadratowymi.

A nawiasy ( i ) używasz tylko wtedy gdy chcesz mieć coś zwrōcone w matches, w Pythonie ta tablica indeksowanana jest od zera. A indeks -1 to zdaje się całość pasująca do wzorca. Najlepiej poczytaj sobie ogólnie o regexprach, bo ja piszę na szybko z pod Androida i nie używam fachowej terminologii, ponieważ wydaję się mi, że oganiam jako tako podstawy regexprów, w sensie umiejętności ich stosowania we w miarę nieskomplikowanych sytuacjach.

0

Podaj może jak wygląda plik (kilka linijek chociaż) i jak powinien wyglądać wynik a jak wygląda. Obecnie program szuka w każdej linijce liczby przynajmniej dwucyfrowej, i pisze TRUE jeśli taką znalazł.

Wzorzec który masz (wzorzec= r'[0-9]{2}') na pewno pasuje do 121212.

Być może chodziło Ci o \d+\s+\d+ (kilka cyfr, kilka białych znaków, kilka cyfr) albo \d{2}\s+\d{3} (dwie cyfry, kilka białych znaków, trzy cyfry)?

0

Używam konsoli do testowania:

import re
wzorzec= r'[0-9]{2}'
kod_pocztowy=raw_input()
dopasowanie = re.search(kod_pocztowy, wzorzec)
if dopasowanie:
	print 'TRUE'
else:
	print 'FALSE'

Konsola:

C:\python>python kod_pocztowy_konsola.py
21
FALSE

C:\python>python kod_pocztowy_konsola.py
2121
FALSE
1

moja propozycja

wzorzec = r"(\d{2}-\d{3})"
kod_pocztowy = 'fdkljlskj k04985ldsfj kldsfj kl4234dsjkldsj klds 99-989 lkefrlwekjr lkej 33-287 3jnkldsnfldskfjlds\n\n\n 88-873kfj'
a = re.findall(wzorzec, kod_pocztowy)
print a

['99-989', '33-287', '88-873']
0

Muszę pobrać tekst z pliku tekstowego. Sądzę że to stanowi problem.

import linecache
import re
i=1
wzorzec= r"((\d{2})-\d{3})"
while 1 :
	linijka= linecache.getline('text.txt',i)
	nowa_linijka=linijka.replace('\n','')
	print  str(len(nowa_linijka))
	i=i+1
	dopasowanie = re.findall(nowa_linijka, wzorzec)
	if dopasowanie: 
		print 'TRUE' +" " + str(i-1)
	else:
		print 'FALSE'
	if not linijka : break

Lepiej było by w tym wypadku użyć match, bo ciąg 898-121212 nie spełnia warunków, albo użyć search i zakotwiczenia,niź findall ,ale no już niech będzie...

 
C:\python>python kod_pocztowy.py
6
FALSE
0
TRUE 2

To wynik, a to plik tekstowy : 90-100 Tylko jedna linijka i kod pocztowy...

Jakieś propozycje?

3
dopasowanie = re.search(kod_pocztowy, wzorzec)

Odwrotnie, wzorzec to pierwszy parametr.

re.search(wzorzec, kod_pocztowy)

I wszystko powinno działać

Swoją drogą przetwarzanie linii moim zdaniem prościej by było zrobić za pomocą

plik = ... # otworzenie
lines = plik.readlines()
plik.close()
for line in lines:
    ... # (przetwarzanie)

Albo jeszcze lepiej

with .... as plik # otworzenie
    lines = plik.readlines()
    for line in lines:
        ... # (przetwarzanie)
2
msm napisał(a):

Albo jeszcze lepiej

with .... as plik # otworzenie
    lines = plik.readlines()
    for line in lines:
        ... # (przetwarzanie)

Możesz po prostu:

with open('...') as plik:
    for line in plik:
        ... # (przetwarzanie)

W dodatku dla dużych plików jest to szybsze i zużywa mniej pamięci (używa iteratora, zamiast pakować cały plik do listy).

1 użytkowników online, w tym zalogowanych: 0, gości: 1