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

Python如何使用特殊符号搜索子字符串?和*(类似RexExp),python,regex,glob,Python,Regex,Glob,我应该为?和*包含子字符串和两个可识别的字符模式来过滤字符串数组 ?-任意一个符号 *-任意数量的任意符号 以数据为例,['baab'、'abbb'、'fc'、'AA']它的工作原理如下: '?b' -> ['baab', 'abbb'] '?a' -> ['baab'] 'c?' -> [] 'b??b' -> ['baab'] '???' -> ['baab', 'abbb'] 'b*b' -> ['baab', 'abbb'] '***' -> [

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

-任意一个符号

*
-任意数量的任意符号

以数据为例,
['baab'、'abbb'、'fc'、'AA']
它的工作原理如下:

'?b' -> ['baab', 'abbb']
'?a' -> ['baab']
'c?' -> []
'b??b' -> ['baab']
'???' -> ['baab', 'abbb']
'b*b' -> ['baab', 'abbb']
'***' -> ['baab', 'abbb', 'fc', 'AA']
我不能在操作符中使用
。
最简单的解决方法是什么?也许它应该是RegExp(但我不确定)或其他东西。

正则表达式的方法是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)])

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

  • (?s)
    -一个内联
    re.DOTALL
    修饰符,也可以使
    匹配换行符
  • -任意1个字符
  • b
    -a
    b
    char
  • *
    -尽可能多的0+字符
如果您需要支持任何glob模式您需要接受glob模式的方法(这就是您的
*
在这里是通配符)

这里唯一的问题是,
fnmatch
globs必须匹配整个输入,而您的模式是未编排的

因此,您需要使用
*
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']
参见。

正则表达式的方法是: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)])

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

  • (?s)
    -一个内联
    re.DOTALL
    修饰符,也可以使
    匹配换行符
  • -任意1个字符
  • b
    -a
    b
    char
  • *
    -尽可能多的0+字符
如果您需要支持任何glob模式您需要接受glob模式的方法(这就是您的
*
在这里是通配符)

这里唯一的问题是,
fnmatch
globs必须匹配整个输入,而您的模式是未编排的

因此,您需要使用
*
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']

请参阅。

您应该使用正则表达式: 对于任何字符,使用一个点- 对于任意数量的字符,请使用一个点后跟一个星- 对于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']

查看完整的参考。

您应该使用正则表达式: 对于任何字符,使用一个点- 对于任意数量的字符,请使用一个点后跟一个星- 对于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']

查看完整参考。

您可以在
可识别字符模式中用
替换“?”,用
*?
替换
来修复模式,并返回至少只包含一个匹配项的
子字符串(
re.search
):

输出:

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

您可以通过在
可识别字符模式中将“?”替换为
并将
*
替换为
*?
来修复模式,并返回至少包含一个匹配项的任何
子字符串(
重新搜索
):

输出:

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

我想说,
***
应该抛出一个错误。在指定的次数内匹配无限数量的字符是没有意义的。或者,这些应该减少到1
*
。@Wiktor Stribiżew我认为你完全正确,但我不是这个案例的任务制定者。好的,找到一个:
import fnmatch
,然后
fnmatch.filter(l,'*{}*'.format(你的ż模式))
。看,我会说,
***
应该抛出一个错误。在指定的次数内匹配无限数量的字符是没有意义的。或者,这些应该减少到1
*
。@Wiktor Stribiżew我认为你完全正确,但我不是这个案例的任务制定者。好的,找到一个:
import fnmatch
,然后
fnmatch.filter(l,'*{}*'.format(你的ż模式))
。不过,请参见
fnmatch
也执行字符类和依赖操作系统的大小写规范化。这个问题听起来更像是家庭作业,而不是直接的shell globbing,因此字符类和大小写规范化可能是不需要的。@user2357112查看更新答案的顶部。这就是你的意思吗?不,因为现在可能有更多不需要的功能,比如正则表达式字符类和组,反斜杠转义等等。(此外,输入模式可能包含应按字面匹配的
字符。)
fnmatch
也执行字符类和依赖操作系统的大小写规范化。这个问题听起来更像是家庭作业,而不是直接的shell globbing,因此字符类和大小写规范化可能是不需要的。@user2357112查看更新答案的顶部。这就是你的意思吗?不,因为现在可能有更多不需要的功能,比如正则表达式字符类和组,反斜杠转义等等。(此外,输入模式可能包含应按字面匹配的
字符。)