2017-03-29 66 views
0

首先,如果标题不是非常明确,很抱歉,我很难对其进行正确表述。这也是为什么我还没有找到问题是否已经被问到,如果有的话。在字符串列表中搜索任意数量的未知子字符串*

所以,我有一个字符串列表,我想执行一个“程序性”搜索,用任何可能的子字符串替换我的target-substring中的每个*
下面是一个例子:

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor('mesh_*') 
# should return: ['mesh_1_TMP', 'mesh_2_TMP'] 

在这种情况下,只有一个*我只是拆分每个字符串*和使用startswith()和/或endswith(),所以没关系。 但是我不知道如果搜索字符串中有多个*如何做同样的事情。

所以我的问题是,如何在字符串列表中搜索任意数量的未知子串来代替*
例如:

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor('*_1_*') 
# should return: ['obj_1_mesh', 'mesh_1_TMP'] 

希望一切都清楚。谢谢。

+4

你可能想看看're'的正则表达式。 – LoicM

+2

解释你如何到达'['mesh_ok1','mesh_ok2']'作为第一个例子的预期输出。 – timgeb

+0

哦,是的,抱歉,那是因为我修改了我的示例代码而未更改结果。我现在编辑它。 – UKDP

回答

1

如果我是你,我会使用正则表达式包。你必须学习一点正则表达式才能做出正确的搜索查询,但这并不算糟糕。 '。+'在这种情况下非常类似于'*'。

import re 

def search_strings(str_list, search_query): 
    regex = re.compile(search_query) 
    result = [] 
    for string in str_list: 
     match = regex.match(string) 
     if match is not None: 
      result+=[match.group()] 
    return result 

strList= ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

print search_strings(strList, '.+_1_.+') 

这应该返回['obj_1_mesh','mesh_1_TMP']。我试图复制'* _1_ *'的情况。对于'mesh_ *',你可以使search_query'mesh _。+'。这里是python正则表达式api的链接:https://docs.python.org/2/library/re.html

+0

这里使用非贪婪匹配可能是一个好主意。 –

+1

是的,直到OP。我使用了贪婪,因为我认为在这个特殊情况下它更直观。 OP如果你想要非贪婪的使用'*'而不是'+'。 – Outis

+0

谢谢!所有的答案都是好的,但是由于这个答案不那么简洁,所以我理解它会更容易(因为我没有使用太多的正则表达式,现在也没有完全理解它)。我也按照建议更改'*'中的'+',我认为这样更精确。 – UKDP

3

考虑使用'fnmatch',它提供类似Unix的文件模式匹配。这里http://docs.python.org/2/library/fnmatch.html

from fnmatch import fnmatch 
strList = ['obj_1_mesh', 
     'obj_2_mesh', 
     'obj_TMP', 
     'mesh_1_TMP', 
     'mesh_2_TMP', 
     'meshTMP'] 

searchFor = '*_1_*' 

resultSubList = [ strList[i] for i,x in enumerate(strList) if fnmatch(x,searchFor) ] 

更多信息本应该做的伎俩

+2

如果您提供了fnmatch的文档链接,并且简要解释了fnmatch的功能,这个答案会更好一些。简单地说,像“fnmatch提供了匹配与unix文件名通配符相似的模式的能力”,您只需要从一个很好的答案中获得这个答案即可。 –

0

如果你一直在寻找的样子字符串中,你可以只使用查找功能时,你会得到这样的:

for s in strList: 
    if s.find(searchFor) != -1: 
     do_something() 

如果您有多个字符串需要查找(如abc * 123 * test),您需要查找每个字符串,找到第二个字符串,从第一个索引开始,它是len等。

1

最简单的方法是使用fnmatch,如ma3oun的答案所示。但是,有一种方法可以使用Regular Expressions,也就是正则表达式。

首先我们改变你的searchFor模式,所以它使用'.+?'作为“通配符”而不是'*'。然后我们将结果编译成一个正则表达式模式对象,以便我们可以有效地使用它多个测试。

有关正则表达式语法的解释,请参阅文档。但简单地说,点意味着任何字符(在这一行上),+意味着寻找它们中的一个或多个,而?意味着进行非贪婪匹配,即,匹配符合模式的最小字符串,而不是最长的字符串(这就是贪婪匹配)。

import re 

strList = ['obj_1_mesh', 
      'obj_2_mesh', 
      'obj_TMP', 
      'mesh_1_TMP', 
      'mesh_2_TMP', 
      'meshTMP'] 

searchFor = '*_1_*' 
pat = re.compile(searchFor.replace('*', '.+?')) 

result = [s for s in strList if pat.match(s)] 
print(result) 

输出

['obj_1_mesh', 'mesh_1_TMP'] 

如果我们使用searchFor = 'mesh_*'结果是

['mesh_1_TMP', 'mesh_2_TMP'] 

请注意,这个解决方案是不强劲。如果searchFor包含在正则表达式中具有特殊含义的其他字符,则它们需要为escaped。实际上,与其进行searchFor.replace转换,首先使用正则表达式语法编写模式会更清晰。