2017-01-17 4 views
1

Hier ist eine wortgetreue Kopie einer Python3 Sitzung zu ignorieren:Boost-regex „kürzestes Spiel“

~/Documents $ python3 
Python 3.5.1 (v3.5.1:37a07cee5969, Dec 5 2015, 21:12:44) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import re 
>>> text = 'This (is) a (test)' 
>>> print(text) 
This (is) a (test) 
>>> re.findall('h', text) 
['h'] 
>>> re.findall('\(.+?\)', text) 
['(is)', '(test)'] 
>>> re.findall('\(.+?\)$', text) 
['(is) a (test)'] 
>>> 

ich die endgültigen findall erwartet zurückzukehren nur(test), wie es für \(.+?\)bei der die kürzeste mögliche Übereinstimmung ist Ende der Zeichenfolge. Stattdessen gibt es (is) a (test) zurück. Es macht das gleiche für längeren Test Strings:

>>> text = 'This (is) (possibly) a (test)' 
>>> re.findall('\(.+?\)', text) 
['(is)', '(possibly)', '(test)'] 
>>> re.findall('\(.+?\)$', text) 
['(is) (possibly) a (test)'] 

Aus welchem ​​Grunde es aus den ersten Auftreten von ( auf überein?

Bitte beachten Sie, dass ich bin nicht auf der Suche nach einer alternativen Regex. Diese Frage bezieht sich auf das spezifische Verhalten, da es falsch zu sein scheint.


Ich habe Python nur verwendet, um zu überprüfen; dies wird durch this question in Adobe InDesign Forum gefragt werden, und InDesign verwendet auch Boost:

Adobe Indesign best of breed-Design bietet: Indesign und es asociated SDK hängt von Boost-Boost.Regex, Boost.Functional und andere.
(http://www.boost.org/users/uses_shrink.html (sic die Fehler))

Antwort

2

Aus welchem ​​Grund ist es aus dem ersten Auftreten von (auf?

übereinstimmen Da der Parser-Zustandsmaschine auf der linken Seite beginnt. Wenn es eine Übereinstimmung gibt, die vom ersten Zeichen beginnt, warum sollte es zurückgewiesen werden?

Das sollte Ihnen einen Anhaltspunkt geben. Sie möchten vermutlich dass kein pare erfordern ntheses tritt in der Mitte: [^(] statt .

Python 2.7.10 (default, Oct 14 2015, 16:09:02) 
[GCC 5.2.1 20151010] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> text = 'This (is) (possibly) a (test)' 
>>> import re 
>>> re.findall('\(.+?\)$', text) 
['(is) (possibly) a (test)'] 
>>> re.findall('\([^(]+?\)$', text) 
['(test)'] 
>>> 
+0

Die Regel „Wenn es eine Übereinstimmung von dem ersten Zeichen ist, warum soll es verworfen werden ..“, mit einem einfachen '\ (. + \)' , sollte nur mit dem ersten '(is)' übereinstimmen. Natürlich gibt es mehr Regeln als diese - die Gierige Regel ist "suche weiter nach dem längsten Spiel". Also, völlig gleichwertig, kann man erwarten, dass eine "kürzeste Übereinstimmung" mit der kürzesten * möglichen Zeichenfolge übereinstimmt. – usr2564301

+0

Es ist die kürzeste Übereinstimmung! Alle anderen kürzeren Matches werden von Ihrer eigenen Anforderung zurückgewiesen, dass sie am Ende des Strings enden muss ("$"). (Ich dachte, ich hätte das nicht erwähnen müssen, da es buchstäblich der einzige Unterschied zu dem Beispiel ist, das Sie gerade zuvor gezeigt haben). Es gibt also die erste mögliche Übereinstimmung, und das Ergebnis ist das kürzeste, das die Kriterien erfüllt. – sehe

+0

... Sprechen wir über die gleichen Testergebnisse? Sicherlich kann man nicht bestreiten, dass die Saite '(test) $' viel kürzer ist als die aktuelle '(ist) a (test) $' - die '$' zur besseren Übersichtlichkeit. "Da die Parser-State-Maschine auf der linken Seite startet" würde bei "This" - aber es ist schlau genug, * das * zu überspringen. Auch eine Überprüfung über das absolut erforderliche Minimum hinaus ist kein Problem (wie es die Standardregel für die Greedy-Prüfung anzeigt). – usr2564301