我编写程序使用正则表达式解析文本。该正则表达式应从用户处获取。我决定使用glob语法作为用户输入,并在内部将glob字符串转换为正则表达式。例如:
"foo.? bar*"
应该转换为
"^.*foo.warw+.*"
不知道怎么逃避字符串中的所有有意义的字符,然后我需要用适当的正则表达式语法替换星号*和问号?字符。这样做最方便的方法是什么?
我编写程序使用正则表达式解析文本。该正则表达式应从用户处获取。我决定使用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