搜索文件以确保单词列表的完全匹配

时间:2018-03-25 11:42:15

标签: python list

围绕这个问题有很多问题,一些使用正则表达式,一些使用开放式,另一些使用,但我发现没有一个适合我的要求。

我正在打开一个包含字符串的xml文件,每行1个。 e.g

<string name="AutoConf_5">setup is in progress…</string>

我想迭代文件中的每一行,并在每行中搜索列表中单词的完全匹配。目前的代码似乎工作并打印出匹配,但它没有完全匹配,例如&#39;传递&#39;发现&#39;通过&#39;,&#39;亲&#39;发现&#39;提供&#39;,&#39;流程&#39;,&#39;继续&#39;等

def stringRun(self,file):
    str_file = ['admin','premium','pro','paid','pass','password','api']
    with open(file, 'r') as sf:
        for s in sf:
            if any(x in str(s) for x in str_file):
                self.progressBox.AppendText(s)

2 个答案:

答案 0 :(得分:0)

而不是使用&#34;&#34;哪个匹配行中的任何子字符串,你应该使用正则表达式&#34; re.search&#34; 我还没有用python检查它,所以很小的语法错误可能会滑入,但这是一般的想法,用你的代码替换if:

if any(re.search(x, str(s)) for x in str_file):

然后,您可以使用正则表达式的强大功能来搜索带有单词边界的列表中的单词。你需要添加&#39; \ b&#39;到每个搜索字符串的开头和结尾,或者添加到条件中的所有字符串:

if any(re.search(r'\b' + x + r'\b', str(s)) for x in str_file):

答案 1 :(得分:0)

如果你想要一个完全匹配,IMO,最好的方法是准备匹配的字符串,然后搜索每一行中的每个字符串。

例如,您可以准备标记字符串和要匹配的字符串之间的映射:

tagged = {'<string name="AutoConf_5">{0}</string>'.format(s): s
          for s in str_file}

dict是您要匹配的标记字符串与实际字符串之间的关联。

你可以这样使用它:

for line in sf:
    line = line.strip()
    if line in tagged:
        self.progressBox.AppendText(tagged[line])

注意:如果您的任何字符串包含&#34;&amp;&#34;,&#34;&lt;&#34;或&#34;&gt;&#34;,您需要转义这些字符,如下所示:

from xml.sax.saxutils import escape

tagged = {'<string name="AutoConf_5">{0}</string>'.format(escape(s)): s
          for s in str_file}

另一种解决方案是使用lxml来解析XML树并查找与给定xpath表达式匹配的节点。

编辑:至少匹配一个单词(组成单词列表)

您有一个包含单词的字符串列表。要匹配至少包含此列表中的单词的XML内容,可以使用正则表达式。

您可能会遇到两个困难:

  • XML内容,解析为文本文件,可以包含&#34;&amp;&#34;,&#34;&lt;&#34;或&#34;&gt;&#34;。所以你需要浏览XML内容。
  • 您的单词列表中的某些单词可能包含RegEx特殊字符(例如&#34; [&#34;或&#34;(&#34;)必须转义。

首先,您可以准备一个RegEx(和一个函数)来查找字符串中单词的所有出现。为此,您可以使用&#34; \ b&#34;匹配空字符串,但仅限于单词的开头或结尾:

str_file = ['admin', 'premium', 'pro', 'paid', 'pass', 'password', 'api']

re_any_word = r"\b(?:" + r"|".join(re.escape(e) for e in str_file) + r")\b"
find_any_word = re.compile(re_any_word, flags=re.DOTALL).findall

例如:

>>> find_any_word("Time has passed")
[]
>>> find_any_word("I pass my exam, I'm a pro")
['pass', 'pro']

要提取XML片段的内容,您还可以使用RegEx(即使在一般情况下不建议使用它,这里值得):

以下RegEx(和函数)匹配"<string>...</string>"片段并选择第一组中的内容:

re_string = r'<string[^>]*>(.*?)</string>'
match_string = re.compile(re_string, flags=re.DOTALL).match

例如:

>>> match_string('<string name="AutoConf_5">setup is in progress…</string>').group(1)
setup is in progress…

现在,您所要做的就是逐行解析文件。

对于演示,我使用了一个字符串列表:

lines = [
    '<string name="AutoConf_5">setup is in progress…</string>\n',
    '<string name="AutoConf_5">it has passed</string>\n',
    '<string name="AutoConf_5">I pass my exam, I am a pro</string>\n',
]

for line in lines:
    line = line.strip()
    mo = match_string(line)
    if mo:
        content = saxutils.unescape(mo.group(1))
        words = find_any_word(content)
        if words:
            print(line + " => " + ", ".join(words))

你得到:

<string name="AutoConf_5">I pass my exam, I am a pro</string> => pass, pro