24

正規表現でテキストを解析するプログラムを作成します。正規表現はユーザーから取得する必要があります。ユーザー入力にglob構文を使用し、内部でglob文字列を正規表現に変換することにしました。例えば:

"foo.? bar*" 

に変換する必要があります

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

どういうわけか、文字列からすべての意味のある文字をエスケープする必要があります。次に、glob *と?を置き換える必要があります。適切な正規表現構文を持つ文字。これを行うための最も便利な方法は何ですか?

4

6 に答える 6

61

不完全または信頼性の低いハッキングは必要ありません。このためにpythonに含まれる関数があります

>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'
于 2009-10-12T17:07:01.437 に答える
3

要件を完全に理解しているかどうかはわかりません。ユーザーが検索に一致するテキスト「エントリ」を見つけたいと思うなら、このブルートな方法が最初にうまくいくと思います。

最初にすべての正規表現をエスケープします。次に、(現在エスケープされている)グロブ文字を置き換えるために非正規表現の置換を使用し、正規表現を構築します。Python では次のようになります。

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

質問の検索文字列については、次のような正規表現が作成されます (raw):

foo\..\ bar.*?

Python スニペットで使用:

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

プロデュース:

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

一致オブジェクトを調べると、一致に関する詳細がわかり、強調表示などに使用できることに注意してください。

もちろん、それ以上のこともあるかもしれませんが、それは出発点であるべきです。

于 2009-01-15T09:47:16.547 に答える
1

私はc++と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();
}

すべて正常に動作しているようです

于 2009-01-15T08:16:17.150 に答える
1

Jakarta OROJava で実装されています

于 2009-01-15T07:44:46.713 に答える
1

jPaq の RegExp.fromWildExp 関数は、これと同様のことを行います。以下は、サイトのフロント ページにある例からの抜粋です。

// 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"));
于 2011-03-14T16:48:04.507 に答える
0

R ではglob2rx、基本ディストリビューションに含まれる関数があります。

http://stat.ethz.ch/R-manual/R-devel/library/utils/html/glob2rx.html

于 2015-06-10T06:16:10.770 に答える