2016-06-07 7 views
0

Ich versuche, alle möglichen (Dinkel-out) Ziffern zu erfassen, außer ich nicht, einen Ausdruck zu schreiben scheinen, die ohne abschließenden/vorhergehenden Raum erfasst.Erfasst alle Ziffern (Dinkel) jede Größe ohne Hinter/führenden Raum

"Wenn es neunzehn tausend sechsundvierzig Bären"

Ergebnis: "Nineteen tausend Vierzig six_" Wunsch: "Nineteen Tausend sechsundvierzig"

Aktuelle Ausdruck:

\b((eleven|twelve|thirteen|fourteen|fifteen|sixteen|seventeen|eighteen|nineteen|twenty|thirty|forty|fifty|sixty|seventy|eighty|ninety|one|two|three|four|five|six|seven|eight|nine|ten|hundred|thousand|million|billion|trillion|and){1}([\–\-\—\‒]|\s){0,1})+\b 

ich habe auch dieses Konzept aus einem anderen Post getestet:

\b(?:(?:one|two|three|four|five|six|seven|eight|nine|zero)\b\s*?){4} 

Whi ch funktioniert gut, aber es erfordert, dass Sie die Größe vorher wissen.

Jede Hilfe wäre toll, ich will es wirklich genau zu erfassen.

+0

Welche Sprache benutzen Sie? –

+0

Try '(your_number_list) (\ s * (your_number_list)) +', wobei 'your_number_list', dass Ihr Fehler ist ** OR ** Liste mit allen möglichen Zahlen Worte. Allerdings ist es ** NICHT ** Aufgabe für die Regexp meiner Meinung nach. – TEXHIK

+0

Ich benutze Perl regexp – killerfred3000

Antwort

1

Um zu vermeiden, Ihr Ergebnis zu trimmen, anstatt Ihr Muster wie folgt zu schreiben: (?: item separator)+, können Sie diese Struktur verwenden: item (?: separator item)*.

Um dies zu tun, wenn "Objekt" lang ist, können Sie auf ein Untermuster in einer Erfassungsgruppe mit dieser Syntax (?n) verweisen, wobei n die Nummer der Erfassungsgruppe ist. Beispiel:

(?xi) # switch on the free-spacing mode and the case-insensitive mode 
\b 
( # capture group 1 
    eleven|twelve|thirt(?:y|een)|four(?:teen)?|fift(?:y|een)|six(?:teen|ty)?| 
    seven(?:teen|ty)?|eight(?:een|y)?|nine(?:teen|ty)?|twenty|forty|one|two|three|five| 
    ten|hundred|thousand|(?:[mb]|tr)illion 
) 
(?> 
    (?:[-–—‒]|\s(?:and\s)?) 
    (?1) # call to the subpattern in the capture group 1 
)* 
\b 

Natürlich können Sie auch die Unter-Pattern anstelle von (?1) umschreiben.

Als beiseite, können Sie die Auswirkungen eines langen Wechsel minimieren, wenn Sie es als ein Baum schreiben und mit dem ersten Zeichen Unterscheidungs ​​Technik:

(?xi) 
\b 
(?=[befhmnost][ehilnoruw]) 
(
    e(?:leven|ight(?:een|y)?) | 
    t(?:w(?:o|e(?:lve|nty))|h(?:irt(?:een|y)|ousand|ree)|en|rillion) | 
    f(?:o(?:ur(?:teen)?|rty)|i(?:ft(?:een|y)|ve)) | 
    s(?:ix(?:t(?:een|y))?|even(?:t(?:een|y))?) | 
    nine(?:t(?:een|y))? | 
    one | 
    hundred | 
    [mb]illion 
) 
(?> (?:[-–—‒]|\s(?:and\s)?) (?1))* 
\b 

demo

+0

Vielen Dank für Ihre Zeit und Hilfe! – killerfred3000

+0

Wow der Baum Ansatz ist mehr als 3 mal so effizient (in Bezug auf Schritte) bei der Erfassung der gleichen Phrase. Das ist eine großartige Technik, danke für die Einsicht. – killerfred3000

0

Sie können einen positiven Blick verwenden -ahead (?=)

Zum Beispiel ((one|two|three|four|and)[- ]{0,1})+(?=)

den Text fett entsprechen w ohne das nachfolgende Leerzeichen.

Foo bar ein zwei-vier und drei yada.

Und wenn die Zahl Text am Ende eines Satzes sein kann, können Sie den positiven Vorgriff zu (?= .)

Dies wird auch die fett ohne entweder Leerzeichen am Ende oder passen anpassen „“

Foo bar ein zwei-vier und drei yada.

Foo bar ein zwei-vier und drei.

+0

Schöne Idee. Ich nehme an, dass ich bei dieser Methode Ausnahmen für jede unmittelbar nachfolgende Interpunktion wie "acht, neun" einfügen müsste. Auch in Fällen von doppelten Leerzeichen wie "eins zwei" kann es immer noch das Markieren des zusätzlichen Speicherplatzes auslösen, da es immer noch die Vorausschauanforderung erfüllt. – killerfred3000

Verwandte Themen