Python中的参数化正则表达式

Python中的参数化正则表达式,python,regex,Python,Regex,在Python中,是否有更好的方法将字符串参数化为正则表达式,而不是像这样手动执行: test = 'flobalob' names = ['a', 'b', 'c'] for name in names: regexp = "%s" % (name) print regexp, re.search(regexp, test) filename = 'bob_20090216.txt' regexps = {'bob': 'bob_[0-9]+.txt',

在Python中,是否有更好的方法将字符串参数化为正则表达式,而不是像这样手动执行:

test = 'flobalob'
names = ['a', 'b', 'c']
for name in names:
    regexp = "%s" % (name)
    print regexp, re.search(regexp, test)
filename = 'bob_20090216.txt'

regexps = {'bob': 'bob_[0-9]+.txt',
           'fred': 'fred_[0-9]+.txt',
           'paul': 'paul_[0-9]+.txt'}

for filetype, regexp in regexps.items():
    m = re.match(regexp, filename)
    if m != None:
        print '%s is of type %s' % (filename, filetype)
这个noddy示例尝试依次匹配每个名称。我知道有更好的方法可以做到这一点,但这只是一个简单的例子,纯粹是为了说明这一点


答案似乎是否定的,没有真正的选择。在python中参数化正则表达式的最佳方法是如上所述,或者使用类似于
str.format()
的派生词,我试图写一个通用问题,而不是“fix ma codez,kthxbye”。对于那些仍然感兴趣的人,我在这里提供了一个更接近我需要的例子:

for diskfilename in os.listdir(''):
    filenames = ['bob.txt', 'fred.txt', 'paul.txt']
    for filename in filenames:
        name, ext = filename.split('.')
        regexp = "%s.*\.%s" % (name, ext)
        m = re.search(regexp, diskfilename)
        if m:
          print diskfilename, regexp, re.search(regexp, diskfilename)
          # ...
我试图根据文件名来计算文件的“类型”,格式为
。在我的真实代码中,
文件名
数组是一个dict,包含一个在找到匹配项后调用的函数

我考虑过的其他方法:

  • 在数组中有一个正则表达式。我已经有了一个没有任何正则表达式魔法的文件名数组,所以我不愿意这样做。我在我的代码中的其他地方做过这件事,但它很混乱(尽管有必要)

  • 仅在文件名的开头匹配。这会起作用,但会破坏文件的.bak副本等。在某个时候,我可能想从文件名中提取日期,因此无论如何都需要使用正则表达式



感谢您的回复,建议使用正则表达式的替代方法来实现相同的最终结果。我现在和将来对正则表达式的参数化更感兴趣。我从来没有遇到过fnmatch,所以从长远来看它非常有用。

好吧,当您从字符串构建regexp时,我看不到其他方法。但您可以使用字典对字符串本身进行参数化:

d = {'bar': 'a', 'foo': 'b'}
regexp = '%(foo)s|%(bar)s' % d
或者,根据问题的不同,您可以使用列表理解:

vlist = ['a', 'b', 'c']
regexp = '|'.join([s for s in vlist])
编辑:Mat澄清了他的问题,这让事情变得不同,上面提到的完全无关

我可能会采用这样的方法:

test = 'flobalob'
names = ['a', 'b', 'c']
for name in names:
    regexp = "%s" % (name)
    print regexp, re.search(regexp, test)
filename = 'bob_20090216.txt'

regexps = {'bob': 'bob_[0-9]+.txt',
           'fred': 'fred_[0-9]+.txt',
           'paul': 'paul_[0-9]+.txt'}

for filetype, regexp in regexps.items():
    m = re.match(regexp, filename)
    if m != None:
        print '%s is of type %s' % (filename, filetype)
输出:

{'bob.txt': ['bob20090217.txt'], 'paul.txt': [], 'fred.txt': []}
对问题先前修订的回答如下:


我不理解您更新的问题,但是
filename.startswith(prefix)
在您的特定情况下可能就足够了

更新问题后,下面的旧答案就不那么相关了


  • 如果您想逐字匹配
    名称,请使用
    re.escape(name)

  • 任何可用于字符串参数化的工具都适用于此处。例如:

    import string
    print string.Template("$a $b").substitute(a=1, b="B")
    # 1 B
    
    或者在Python 2.6+中使用:

    print "{0.imag}".format(1j+2)
    # 1.0
    

  • 可能和模块对您有帮助吗?

    +1我检查了文档,以确保没有办法做到这一点(除了您所说的参数化字符串)。我认为Python不需要它。@paprika:我已经澄清了这个例子,以便更好地解释我的意思@David:我自己在文档中找不到任何东西,但我认为这是很常见的,会有一些东西-可能是一些东西以这种方式使用字符串。
    如果m:
    在这种情况下就足够了。通常,如果obj不是None,则
    优于
    如果obj!=没有
    @J.F.塞巴斯蒂安:的确,“如果m:…”就足够了。不知何故,我坚持了这一点,因为我学会了避免使用简短的“if v:…”来检查布尔真/假(这是一个完全不同的故事)。你能详细说明为什么“不是”更好吗?仅仅因为可读性或其他原因?
    is
    检查对象标识(内存中的对象地址),因此它是高效的,但我使用这种形式纯粹是为了可读性。如果你问一个关于你的具体案例的问题,你可能会得到更好的答案。我更多的是在了解正则表达式参数化之后,而不是修改我的家庭作业kthxbye。请参见上文。我只有一条您可能已经知道的注释,但我想确定——当反复使用同一个正则表达式时,如果您首先使用:p=re编译它们,您将看到更好的性能。compile(s)您的示例(以及响应中的其他人)不会这样做。公平点,但请参见