Python中的通配符列表匹配

时间:2019-02-12 09:28:49

标签: python

我有一个字符串列表

DashboardComponent

路径就像

l = [
   '/api/users/*',
   '/api/account/*
]

如果路径在列表/api/users/add/ /api/users/edit/1 /api/users/ /api/account/view/1 /api/account/ 中,该如何对它们执行过滤。

条件类似

l

对于上面的所有给定路径,应返回'/api/users/add/' in l

6 个答案:

答案 0 :(得分:2)

l = [
   '/api/users/*',
   '/api/account/'
]

paths = [
'/api/users/add/'
'/api/users/edit/1',
'/api/users/',
'/api/account/view/1',
'/api/account/'
]

for path in paths:
    if path in l:
        print("Path: {}, found in the list".format(path))

输出:

Path: /api/account/, found in the list

编辑:

如果您想要一个将返回布尔值的方法:

l = [
   '/api/users/*',
   '/api/account/'
]

paths = [
'/api/users/add/',
'/api/users/edit/1',
'/api/users/',
'/api/account/view/1',
'/api/account/'
]

def checkPath(path):
        if path in l:
            return True
        else:
            return False

for i in range(0,len(paths)):
    print(checkPath(paths[i]))

输出:

False
False
False
False
True

编辑2:

如果您希望*与路径匹配,则可以从原始列表中删除*,然后像这样进行迭代:

def checkPath(path):
        if path in l_new:
            return True
        else:
            return False

# strip the asterick
l_new = [s.strip('*') for s in l]

for i in range(0,len(paths)):
    print(checkPath(paths[i]))

输出:

False
False
True
False
True

答案 1 :(得分:2)

如果我理解正确,那么您想看看通配符模式是否成立。为此,您可以使用fnmatch中的glob模块。假设你有这个:

l = [
   '/api/users/*',
   '/api/account/*'
]

paths = [
   '/api/users/add/'
   '/api/users/edit/1',
   '/api/users/',
   '/api/account/view/1',
   '/api/account/',
   '/non/existent/path'
]

你可以得到这个:

>>> import fnmatch
>>> [any(fnmatch.fnmatch(path, pat) for pat in l) for path in paths]
[True, True, True, True, False]

答案 2 :(得分:1)

如果通配符始终是查询字符串中的最后一件事,则建议将其截断并使用.startswith()。否则,请使用fnmatch模块来解释“ glob”样式的通配符:

from fnmatch import fnmatch

def listglob(path, patterns):
    return any(fnmatch(path, pat) for pat in patterns)

for path in paths:
    print(path, listglob(path, l))

答案 3 :(得分:1)

肯定已经建议针对此问题发布已经发布的fnmatch解决方案,但是,以下答案显示了非导入解决方案:

def matchs_path(_pattern, _input):
  _a, _b = filter(None, _pattern.split('/')), filter(None, _input.split('/'))
  while True:
    _val, _val2 = next(_a, None), next(_b, None)
    if _val is None and _val2 is None:
      return True
    if _val != '*' and _val != _val2:
      return False
    if _val == "*":
      _to_see = next(_a, None)
      if _to_see is None:
        return True
      while True:
        c = next(_b, None)
        if c is None:
          return True
        if c == _to_see:
          break

patterns = ['/api/users/*', '/api/account/*', '/new/*/test/here']
data = ['/api/users/add/', '/api/users/edit/1', '/api/users/', '/api/account/view/1', '/api/account/', '/going/to/fail/here', '/new/additional/abc/test/here']
new_results = {i:{c:matchs_path(i, c) for c in data} for i in patterns}

输出:

{
 "/api/users/*": {
    "/api/users/add/": true,
    "/api/users/edit/1": true,
    "/api/users/": true,
    "/api/account/view/1": false,
    "/api/account/": false,
    "/going/to/fail/here": false,
    "/new/additional/abc/test/here": false
 },
  "/api/account/*": {
    "/api/users/add/": false,
    "/api/users/edit/1": false,
    "/api/users/": false,
    "/api/account/view/1": true,
    "/api/account/": true,
    "/going/to/fail/here": false,
    "/new/additional/abc/test/here": false
 },
 "/new/*/test/here": {
    "/api/users/add/": false,
    "/api/users/edit/1": false,
    "/api/users/": false,
    "/api/account/view/1": false,
    "/api/account/": false,
    "/going/to/fail/here": false,
    "/new/additional/abc/test/here": true
  }
}

答案 4 :(得分:0)

或列表理解:

print('\n'.join(['Path: {}, found in the list'.format(path) for path in paths if path in l]))

答案 5 :(得分:0)

您可以使用正则表达式将路径模式末尾的*替换为.*,然后将它们用作正则表达式本身以匹配列表中的路径。

paths = ['/api/users/add/',
         '/api/users/edit/1',
         '/api/users/',
         '/api/account/view/1',
         '/api/account/',
         '/not/a/valid/path']
l = ['/api/users/*', '/api/account/*']
patterns = [re.compile(re.sub("\*$", ".*", s)) for s in l]

>>> [path for path in paths if any(p.match(path) for p in patterns)]
['/api/users/add/',
 '/api/users/edit/1',
 '/api/users/',
 '/api/account/view/1',
 '/api/account/']