2015-07-13 10 views
6

Oto regex - próbował przez egrep, a następnie przez Python 2.7:"Nic nie powtórzyć" z Pythona regex

$ echo '/some/path/to/file/abcde.csv' | Egrepuj '* ([a-zA-Z] +) CSV.

/tam/ścieżka/do/pliku/abcde.csv

Jednakże samo wyrażenie regularne w Pythonie

re.match(r'*([a-zA-Z]+)\.csv',f) 

daje:

Traceback (most recent call last): 
    File "/shared/OpenChai/bin/plothost.py", line 26, in <module> 
    hosts = [re.match(r'*([a-zA-Z]+)\.csv',f).group(1) for f in infiles] 
    File "/usr/lib/python2.7/re.py", line 141, in match 
    return _compile(pattern, flags).match(string) 
    File "/usr/lib/python2.7/re.py", line 251, in _compile 
    raise error, v # invalid expression 
sre_constants.error: nothing to repeat 

Doing wyszukiwanie ujawnia wydaje się być błąd Python w grze tutaj:

regex error - nothing to repeat

Wydaje się, że błąd Pythona (który działa idealnie w vim). Źródłem problemu jest bit (\ s * ...) +.

Jednak to nie jest dla mnie jasne: co następnie jest obejście mojego regex wykazano powyżej - aby pyton szczęśliwy?

Dzięki.

+2

Czy próbowałeś '. *' Lub '. *?'? –

+0

To nie jest błąd Pythona; masz '*' (co oznacza "poprzedni znak powtórzony 0 lub więcej razy") bez poprzedniej litery. –

+0

'*' w regex oznacza '0 lub więcej poprzedniego', więc to, na co narzekasz, to błąd wcale nie jest błędem. Co chcesz, aby '*' pasowało? –

Odpowiedz

3

Nie potrzebujesz * we wzorze, to powoduje problem.

Zastosowanie

([a-zA-Z]+)\.csv 

Albo dopasować cały ciąg:

.*([a-zA-Z]+)\.csv 

Zobacz demo

Powodem jest to, że * jest Niecytowany i dlatego jest traktowany jako kwantyfikator. Jest on stosowany do poprzedniego podtekstu w regex. Tutaj jest on używany na początku wzorca, a zatem nie może nic określić ilościowo. Tak więc, nic nie powtórzyć jest zgłaszane.

Jeśli ona „działa” w VIM, to tylko dlatego, VIM regex silnik ignoruje ten podciąg wzorca (tak samo jak robi Java z przed zmianą [ i ] wewnątrz klasy postaci jak [([)]]).

+0

Rozumiem. Więc dlaczego działa egrep? – javadba

+0

Jest to po prostu ignorowane. Python nie może tego zignorować, ponieważ prawdopodobnie jest to błąd ludzki. –

3

To nie jest silnik python-regex używający tradycyjnego NFA do dopasowywania wzorców. i znak * działa tylko wtedy, gdy poprzedzony jest tokenem.

'*'

Powoduje otrzymany RE dopasować 0 lub więcej powtórzeń poprzednich RE, ponieważ wiele powtórzeń, ile jest możliwe. ab * będzie pasować do "a", "ab" lub "a", po których następuje dowolna liczba "b".

Zamiast więc można używać .* które powtarzają dowolny znak (.):

r'.*([a-zA-Z]+)\.csv' 

Python także dostarczenie modułu fnmatch które wspierają Unix shell stylu symbole wieloznaczne.

>>> import fnmatch 
>>> s="/some/path/to/file/abcde.csv" 
>>> fnmatch.fnmatch(s, '*.csv') 
True