Python 如何用特殊符号搜索子字符串? 和 *(类似 RexExp)



我应该通过包含子字符串和两个可识别的字符模式来过滤字符串数组,用于?*

?- 一个任意符号

*- 任意数量的任何符号

以数据['baab', 'abbb', 'fc', 'AA']为例,它的工作方式应为:

'?b' -> ['baab', 'abbb']
'?a' -> ['baab']
'c?' -> []
'b??b' -> ['baab']
'???' -> ['baab', 'abbb']
'b*b' -> ['baab', 'abbb']
'***' -> ['baab', 'abbb', 'fc', 'AA']

我不能使用它in运算符。 解决它最简单的方法是什么?也许它应该是正则表达式(但我不确定(或其他东西。

正则表达式方法是 1( 收缩所有连续的*s,2(re.escape?*和 3( 之间的部分,将每个*替换为.*?替换为.,同时使用re.DOTALL修饰符编译正则表达式:

import re
def repl(m):
res = "{}{}".format(re.escape(m.group(1)), m.group(2).replace("*", ".*").replace("?", "."))
if m.group(3):
res += re.escape(m.group(3))
return res
def glob_to_regex(glob):
glob = re.sub(r'*{2,}', '*', glob)
return '(?s)' + re.sub(r'([^?*]*)([*?]+)([^?*]+$)?', repl , glob)
l = ['baab', 'abbb', 'fc', 'AA', 'abb.']
print([x for x in l if re.search(glob_to_regex('?b*b'), x)])
print([x for x in l if re.search(glob_to_regex('?b*.'), x)])

请参阅 Python 演示。

在这里,像?b***这样的模式将被转换为(?s).b.*模式,这意味着:

  • (?s)- 一个内联re.DOTALL修饰符,也会.匹配换行符
  • .- 任意 1 个字符
  • b-b
  • .*- 尽可能多地使用任何 0+ 字符。

如果您需要支持任何glob模式,则需要接受 glob 模式fnmatch.filter(names, pattern)方法(这就是您的?*在这里,通配符(。

这里的独特问题是,当您的模式未锚定时,fnmatch球必须与整个输入匹配。

因此,您需要用*s 包装您的模式:

import fnmatch
l = ['baab', 'abbb', 'fc', 'AA']
print(fnmatch.filter(l, '*{}*'.format('?b')))
print(fnmatch.filter(l, '*{}*'.format('?a')))
print(fnmatch.filter(l, '*{}*'.format('c?')))
print(fnmatch.filter(l, '*{}*'.format('b??b')))
print(fnmatch.filter(l, '*{}*'.format('???')))
print(fnmatch.filter(l, '*{}*'.format('b*b')))
print(fnmatch.filter(l, '*{}*'.format('***')))

输出:

['baab', 'abbb']
['baab']
[]
['baab']
['baab', 'abbb']
['baab', 'abbb']
['baab', 'abbb', 'fc', 'AA']

请参阅 Python 演示。

您可以通过将"?"替换为.并将*替换为recognizable character patterns中的.*?来修复模式,并返回至少仅包含一个匹配项的任何substring(re.search(:

import re
example = ['baab', 'abbb', 'fc', 'AA']
def filter_by_pattern(elements, pattern):
# convert `?` and `*` flags
pattern = pattern.replace('?', '.').replace('*', '.*?')
# you could make this a generator instead of list if you like
return [substring for substring in elements if re.search(pattern, substring)]
print(filter_by_pattern(example , '?b'))
print(filter_by_pattern(example , '?a'))
print(filter_by_pattern(example , 'c?'))
print(filter_by_pattern(example , 'b??b'))
print(filter_by_pattern(example , '???' ))
print(filter_by_pattern(example , 'b*b' ))
print(filter_by_pattern(example , '***' ))

输出:

['baab', 'abbb']
['baab']
[]
['baab']
['baab', 'abbb']
['baab', 'abbb']
['baab', 'abbb', 'fc', 'AA']

你应该使用正则表达式: 对于任何字符,使用一个点 - 对于任意数量的字符,请使用一个点后跟一个星号 - 对于 0 或 1 个字符,请使用一个点,后跟疑问标记。

import re
define shortlist (pattern, list):
return [s for s in list if re.search(pattern, s)]
mylist = ['baab', 'abbb', 'fc', 'AA']
l = shortlist('.b', mylist)  # l = ['baab', 'abbb']
l = shortlist('.a', mylist)  # l = ['baab']
l = shortlist('b..b', mylist)  # l = ['baab']
l = shortlist('b.*b', mylist)  # l = ['baab', 'abbb']
l = shortlist('.{3}', mylist) # l = ['baab', 'abbb']

查看 https://docs.python.org/3/library/re.html 以获取完整参考。

最新更新