从 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 表达式创建正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

如何使用正则表达式 (glob) 搜索文件树

找出两个 Glob 模式(或正则表达式)的匹配项是不是相交的算法

在 Python 脚本中使用正则表达式 [重复]

glob通配符

正则表达式点到行尾

正则表达式及相关内容