从 glob 表达式创建正则表达式
Posted
技术标签:
【中文标题】从 glob 表达式创建正则表达式【英文标题】:Create regex from glob expression 【发布时间】:2010-10-01 13:09:09 【问题描述】:我编写了用正则表达式解析文本的程序。正则表达式应从用户处获取。我打算对用户输入使用 glob 语法,并在内部将 glob 字符串转换为正则表达式。例如:
"foo.? bar*"
应该转换成
"^.*foo\.\w\bar\w+.*"
不知何故,我需要从字符串中转义所有有意义的字符,然后我需要替换 glob * 和 ?具有适当正则表达式语法的字符。最方便的方法是什么?
【问题讨论】:
正则表达式看起来有点奇怪。比如:“^.*foo”可以写成“foo”。而且我认为 globbing 星转换为正则表达式“。*?”。搜索的空间去哪儿了? \bar 匹配以“ar”开头的单词。 【参考方案1】:Jakarta ORO 有一个implementation in Java。
【讨论】:
【参考方案2】:我使用 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();
看起来一切正常
【讨论】:
【参考方案3】:我不确定我是否完全理解这些要求。如果我假设用户想要找到他们的搜索匹配的文本“条目”,那么我认为这种粗暴的方式可以作为一个开始。
首先转义所有对正则表达式有意义的东西。然后使用非正则表达式替换来替换(现在转义的)全局字符并构建正则表达式。就像在 Python 中一样:
regexp = re.escape(search_string).replace(r'\?', '.').replace(r'\*', '.*?')
对于问题中的搜索字符串,这会构建一个看起来像这样(原始)的正则表达式:
foo\..\ bar.*?
在 Python sn-p 中使用:
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"
请注意,如果您检查匹配对象,您可以了解有关匹配的更多信息并用于突出显示或其他用途。
当然,可能还有更多,但这应该是一个开始。
【讨论】:
没错,但您还需要在搜索字符串中替换 ()|\ [] 和其他有意义的字符【参考方案4】:不需要不完整或不可靠的黑客攻击。有一个函数包含在 python 中
>>> import fnmatch
>>> fnmatch.translate( '*.foo' )
'.*\\.foo$'
>>> fnmatch.translate( '[a-z]*.txt' )
'[a-z].*\\.txt$'
【讨论】:
如果您使用 python 创建正则表达式,那么您应该使用 python 来使用正则表达式进行比较,因为 sed 不理解 fnmatch 实际输出的尾随 '\\Z(?ms)' .translate. 当你需要一个函数时,谷歌搜索一个sn-p,发现这个函数在一个内置库中,这种感觉真是太棒了。这就是我喜欢 python 的原因。【参考方案5】: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"));
【讨论】:
【参考方案6】:在 R 中,基本分布中包含 glob2rx
函数:
http://stat.ethz.ch/R-manual/R-devel/library/utils/html/glob2rx.html
【讨论】:
以上是关于从 glob 表达式创建正则表达式的主要内容,如果未能解决你的问题,请参考以下文章