opening Erstellen Sie Regex aus dem Glob-Ausdruck



regex match opening tag (6)

Ich schreibe Programm, das Text mit regulärem Ausdruck analysiert. Regulärer Ausdruck sollte vom Benutzer erhalten werden. Ich bevorzuge die Verwendung der Glob-Syntax für die Benutzereingabe und die interne Konvertierung von Glob-String in den regulären Ausdruck. Beispielsweise:

"foo.? bar*" 

sollte in konvertiert werden

"^.*foo\.\w\bar\w+.*"

Irgendwie muss ich alle sinnvollen Zeichen aus der Zeichenfolge entfernen, dann muss ich glob * ersetzen und? Zeichen mit entsprechender Regexp-Syntax. Was ist der bequemste Weg, dies zu tun?



Answer #2

Ich bin mir nicht sicher, ob ich die Anforderungen vollständig verstanden habe. Wenn ich annehme, dass die Benutzer Text "Einträge" suchen wollen, wo ihre Suche übereinstimmt, dann denke ich, dass dieser rohe Weg als ein Anfang funktionieren würde.

Zuerst entkommt alles Regex-sinnvoll. Verwenden Sie dann Nicht-Regex-Ersetzungen, um die (jetzt maskierten) Glob-Zeichen zu ersetzen und den regulären Ausdruck zu erstellen. Wie in Python:

regexp = re.escape(search_string).replace(r'\?', '.').replace(r'\*', '.*?')

Für die Suchzeichenfolge in der Frage wird eine Regexp erstellt, die wie folgt aussieht (roh):

foo\..\ bar.*?

Wird in einem Python-Snippet verwendet:

search = "foo.? bar*"
text1 = 'foo bar'
text2 = 'gazonk foo.c bar.m m.bar'

searcher = re.compile(re.escape(s).replace(r'\?', '.').replace(r'\*', '.*?'))

for text in (text1, text2):
  if searcher.search(text):
    print 'Match: "%s"' % text

Produziert:

Match: "gazonk foo.c bar.m m.bar"

Beachten Sie, dass Sie, wenn Sie das Übereinstimmungsobjekt untersuchen, mehr über die Übereinstimmung herausfinden und zur Hervorhebung oder was auch immer verwenden können.

Natürlich könnte es mehr geben, aber es sollte ein Anfang sein.



Answer #4

keine Notwendigkeit für unvollständige oder unzuverlässige Hacks. Es gibt eine Funktion, die in Python enthalten ist

>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'

Answer #5

jpaqs RegExp.fromWildExp Funktion tut etwas ähnliches. Das folgende Beispiel stammt aus dem Beispiel auf der ersten Seite der Site:

// Find a first substring that starts with a capital "C" and ends with a
// lower case "n".
alert("Where in the world is Carmen Sandiego?".findPattern("C*n"));

// Finds two words (first name and last name), flips their order, and places
// a comma between them.
alert("Christopher West".replacePattern("(<*>) (<*>)", "p", "$2, $1"));

// Finds the first number that is at least three numbers long.
alert("2 to the 64th is 18446744073709551616.".findPattern("#{3,}", "ol"));

Answer #6

Ich schreibe meine eigene Funktion mit C ++ und boost :: regex

std::string glob_to_regex(std::string val)
{
    boost::trim(val);
    const char* expression = "(\\*)|(\\?)|([[:blank:]])|(\\.|\\+|\\^|\\$|\\[|\\]|\\(|\\)|\\{|\\}|\\\\)";
    const char* format = "(?1\\\\w+)(?2\\.)(?3\\\\s*)(?4\\\\$&)";
    std::stringstream final;
    final << "^.*";
    std::ostream_iterator<char, char> oi(final);
    boost::regex re;
    re.assign(expression);
    boost::regex_replace(oi, val.begin(), val.end(), re, format, boost::match_default | boost::format_all);
    final << ".*" << std::ends;
    return final.str();
}

Es sieht so aus, als ob alles gut funktioniert





glob