2015-04-22 7 views
7

Mam plik .txt, który wygląda jak ciąg znaków s. Ciąg s jest formowana przez word_1 następnie word_2id i number:Jak naprawić wyrażenie regularne, które ma uchwycić słowo i identyfikator?

word_1 word_2 id number 

Chciałbym utworzyć regex że złapać na liście wszystkie ocurrences tego słowa "nunca" następnie id VM_ _ _ _. constrait wyodrębnić wzór "nunca" i VM_ _ _ _ jest to, że ocurrences musi znajdować się jeden po drugim, w którym _ są wolne postacie ciągu id np :

nunca nunca RG 0.293030 
first_word second_word VM223FDS 0.902333 
error errpr RG 0.345355667 
nunca nunca RG 0.1489098 
ninguna ninguno DI0S3DF 0.345344 
third fourth VM34SDF 0.7865489 

Jest to wzór chciałbym wyodrębnić ponieważ są one umieszczone jeden za drugim. A to będzie sygnał wyjściowy w formie listy:

[(nunca,RG),(second_word, VM223FDS)] 

Przykładowo będzie to źle, ponieważ nie są one jeden po drugim:

nunca nunca RG 0.293030 
prendas prenda NCFP000 0.95625 
success success VM23434SDF 0.902333 

Więc dla struny s:

s = '''Vaya ir VMM03S0 0.427083 
mañanita mañana RG 0.796611 
, , Fc 1 
buscando buscar VMG0000 1 
una uno DI0FS0 0.951575 
lavadora lavadora NCFS000 0.414738 
con con SPS00 1 
la el DA0FS0 0.972269 
que que PR0CN000 0.562517 
sorprender sorprender VMN0000 1 
a a SPS00 0.996023 
una uno DI0FS0 0.951575 
persona persona NCFS000 0.98773 
muy muy RG 1 
especial especial AQ0CS0 1 
para para SPS00 0.999103 
nosotros nosotros PP1MP000 1 
, , Fc 1 
y y CC 0.999962 
la lo PP3FSA00 0.0277039 
encontramos encontrar VMIP1P0 0.65 
. . Fp 1 

Pero pero CC 0.999764 
vamos ir VMIP1P0 0.655914 
a a SPS00 0.996023 
lo el DA0NS0 0.457533 
que que PR0CN000 0.562517 
interesa interesar VMIP3S0 0.994868 
LO_QUE_INTERESA_La lo_que_interesa_la NP00000 1 
lavadora lavador AQ0FS0 0.585262 
tiene tener VMIP3S0 1 
una uno DI0FS0 0.951575 
clasificación clasificación NCFS000 1 
A+ a+ NP00000 1 
, , Fc 1 
de de SPS00 0.999984 
las el DA0FP0 0.970954 
que que PR0CN000 0.562517 
ahorran ahorrar VMIP3P0 1 
energía energía NCFS000 1 
, , Fc 1 
si si CS 0.99954 
no no RN 0.998134 
me me PP1CS000 0.89124 
equivoco equivocar VMIP1S0 1 
. . Fp 1 

Lava lavar VMIP3S0 0.397388 
hasta hasta SPS00 0.957698 
7 7 Z 1 
kg kilogramo NCMN000 1 
, , Fc 1 
no no RN 0.998134 
está estar VAIP3S0 0.999201 
nada nada RG 0.135196 
mal mal RG 0.497537 
, , Fc 1 
se se P00CN000 0.465639 
le le PP3CSD00 1 
veía ver VMII3S0 0.62272 
un uno DI0MS0 0.987295 
gran gran AQ0CS0 1 
tambor tambor NCMS000 1 
((Fpa 1 
de de SPS00 0.999984 
acero acero NCMS000 0.973481 
inoxidable inoxidable AQ0CS0 1 
)) Fpt 1 
y y CC 0.999962 
un uno DI0MS0 0.987295 
error error NCFSD23 0.234930 
error error VMDFG34 0.98763 
consumo consumo NCMS000 0.948927 
máximo máximo AQ0MS0 0.986111 
de de SPS00 0.999984 
49 49 Z 1 
litros litro NCMP000 1 
error error DI0S3DF 1 
Mandos mandos NP00000 1 
intuitivos intuitivo AQ0MP0 1 
, , Fc 1 
todo todo PI0MS000 0.43165 
muy muy RG 1 
bien bien RG 0.902728 
explicado explicar VMP00SM 1 
, , Fc 1 
jamas jamas RG 0.343443 
nada nada PI0CS000 0.850279 
que que PR0CN000 0.562517 
ver ver VMN0000 0.997382 
con con SPS00 1 
la el DA0FS0 0.972269 
lavadora lavadora NCFS000 0.414738 
de de SPS00 0.999984 
nunca nunca RG 0.903 
casa casa NCFS000 0.979058 
de de SPS00 0.999984 
mis mi DP1CPS 0.995868 
error error VM9032 0.234323 
string string VMWEOO 0.03444 
padres padre NCMP000 1 
Además además NP00000 1 
incluye incluir VMIP3S0 0.994868 
la el DA0FS0 0.972269 
tecnología tecnología NCFS000 1 
error errpr RG2303 1 
Textileprotec textileprotec NP00000 1 
que que PR0CN000 0.562517 
protege proteger VMIP3S0 0.994868 
nuestras nuestro DP1FPP 0.994186 
ninguna ninguno DI0S3DF 0.345344 
falla falla NCFSD23 1 
prendas prenda NCFP000 0.95625 
más más RG 1 
preciadas preciar VMP00PF 1 
jamas jamas RG2303 1 
string string VM9032 0.234323 
nunca nunca RG 0.293030 
success success VM23SDF 0.902333 
. . Fp 1''' 

to co starałem:

import re 
pattern__ = re.findall(r'(?m)^.*?\b(nunca)\s+(\S+)\s+[0-9.]+\n.*?\s(\S+)\s+(VM\S+)\s+[0-9.]+$', s) 

print pattern__ 

Problem z tym podejściem polega na tym, że zwraca pustą listę: []. Każdy pomysł jak rozwiązać ten problem, w celu uzyskania:

[('nunca','RG'),('success','VM23SDF')] 

z góry dzięki chłopaki!

+0

Opcja 'VM' id zawsze następuje nieokreślony zbiór łańcuchów i liczb, na przykład:' VM998SFE' –

Odpowiedz

1

Making jakieś założenie o jednorodności formatu, a jeśli rozumiem dobrze, że to możliwe, aby wyszukać tylko word_2, wówczas wyrażenie regularne może być bardzo prosta:

regex = re.compile("(nunca)\s(\S+)\s\d\S*\n\S+\s(\S+)\s(VM)", re.MULTILINE) 
regex.findall(string) 

ja nie jestem użytkownik Python, testowałem mój regex here

UPDATE Po korekcie John wykonany, nowy regex będą:

regex = re.compile("(nunca)\s(\S+)\s\d\S*\n\S+\s(\S+)\s(VM)(\S+)?", re.MULTILINE) 
regex.findall(string) 

W ten sposób będziesz w stanie złapać zarówno VM, jak i ID. Jeśli chcesz je razem po prostu zmienić (VM\S+)

+0

Dzięki za pomoc zapomniałem wspomnieć, że po id "VM" następują inne ciągi. Muszę złapać wszystkie identyfikatory, które mają jako pierwszy ciąg znaków "VM". Każdy pomysł, jak to naprawić? –

+0

Masz na myśli VM plus numer, jak VM1234? – ColOfAbRiX

+0

Tak, plus liczba podobna do 'VM1234' lub ciąg taki jak' VM1234SDE' –

1

Chyba ten regex pomaga:

ur'.*?\b(nunca)\s+(\S+)\s+[0-9.]+[\r\n]+\S+\s+(\S+)\s+(VM\S+)\s+[0-9.]+' 

Zobacz demo.

+0

Dzięki za pomoc, zapomniałem wspomnieć, że 'VM' id następują inne ciągi. Muszę złapać wszystkie identyfikatory, które mają jako pierwszy ciąg znaków "VM". Każdy pomysł, jak to naprawić ?. Zmontowałem quesiton. –

+0

Czy możesz jeszcze raz sprawdzić? Właśnie dodałem z powrotem '\ S +' do '(VM \ S +)'. Wydaje się, że działa dobrze. Zauważ, że csv i inne parsery mogą być naprawdę dobre. Nadal wierzę w wyrażenia regularne :). –

1

Można przetworzyć pliku wiersz po wierszu sprawdzanie parę wierszy za każdym razem:

import csv 
with open("in.txt") as f: 
    reader = csv.reader(f,delimiter=" ") 
    prev = next(reader) 
    for row in reader: 
     if "VM" in row and "nunca" in prev: 
      nun, val, = prev[-3:-1] 
      wrd, i = row[-3:-1] 
      print(nun, val, wrd, i) 
     prev = row 

('nunca', 'RG', 'success', 'VM') 

prawie 20 razy szybciej niż przy użyciu wyrażenia regularnego:

In [1]: %%timeit 
    ...: with open("test.txt") as f: 
    ...:  import re 
    ...:  pr= re.findall(ur'.*?\b(nunca)\s+(\S+)\s+[0-9.]+[\r\n]+\S+\s+(\S+)\s+(VM)\s+[0-9.]+',f.read()) 
    ...: 
1000 loops, best of 3: 936 µs per loop 

In [2]: import csv 

In [3]: %%timeit 
    ...: with open("test.txt") as f: 
    ...:  reader = csv.reader(f,delimiter=" ") 
    ...:  prev = next(reader) 
    ...:  for row in reader: 
    ...:   if "VM" in row and "nunca" in prev: 
    ...:    nun, val, = prev[-3:-1] 
    ...:    wrd, i = row[-3:-1] 
    ...: 
10000 loops, best of 3: 59 µs per loop 

Dla aktualizacji:

import csv 
with open(in.txt") as f: 
    reader = csv.reader(f,delimiter=" ") 
    prev = next(reader) 
    for row in reader: 
     if len(row) < 2: 
      continue 
     if row[-2].startswith("VM") and "nunca" in prev: 
      nun, val, = prev[-3:-1] 
      wrd, i = row[-3:-1] 
      print(nun, val, wrd, i) 
     prev = row 

('nunca', 'RG', 'success', 'VM23SDF') 

Wydaje się, że na podstawie wprowadzonych danych VM___ jest zawsze drugim ostatnim elementem, jeśli może być w dowolnym miejscu w rzędzie:

`if any(ele.startswith("VM") for ele in row)` 
+0

Wow, dzięki, nie zbadałem tego podejścia !. Być może regex utrudnia to zadanie! –

+1

Bez zmartwień, '59 μs vs 936 μs' dla wyrażeń regularnych. –

+0

Dzięki za pomoc zapomniałem wspomnieć, że id "VM" jest śledzony przez inne ciągi. Muszę złapać wszystkie identyfikatory, które mają jako pierwszy ciąg znaków "VM". Zmontowałem quesiton. –

Powiązane problemy