English 中文(简体)
从glob表达式创建正则表达式
原标题:
  • 时间:2009-01-15 07:16:36
  •  标签:

我编写程序使用正则表达式解析文本。该正则表达式应从用户处获取。我决定使用glob语法作为用户输入,并在内部将glob字符串转换为正则表达式。例如:

"foo.? bar*" 

应该转换为

"^.*foo.warw+.*"

不知道怎么逃避字符串中的所有有意义的字符,然后我需要用适当的正则表达式语法替换星号*和问号?字符。这样做最方便的方法是什么?

问题回答

不需要不完整或不可靠的黑客技巧。Python中包含了这个功能。

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

我不确定我完全理解要求。如果我假设用户希望找到其搜索匹配的文本“条目”,那么我认为这种粗暴的方式可以作为一个起点。

首先,逃离所有正则表达式相关的内容。然后使用非正则表达式替换(现在已转义的)全局字符,并构建正则表达式。在Python中的示例代码如下:

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

对于问题中的搜索字符串,这会构建一个看起来像这样的正则表达式(原始):

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"

请注意,如果您检查匹配对象,您可以了解更多有关匹配的信息,并用于高亮显示或其他用途。

当然,这可能还有更多,但这应该是一个开始。

Jakarta ORO在Java中有一个实现。

我编写了自己的函数,使用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();
}

看起来一切都正常运作。

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"));

在 R 中,基本分发中包含 glob2rx 函数:

将此翻译成中文:http://stat.ethz.ch/R-manual/R-devel/library/utils/html/glob2rx.html http://stat.ethz.ch/R-manual/R-devel/library/utils/html/glob2rx.html





相关问题
热门标签