如果尚不存在,则将字符串写入循环中的文件

时间:2016-08-17 07:08:48

标签: python

这已经被问及并回答了,我已经阅读了很多这些帖子......但由于某些原因,我的代码不起作用。希望有人可以提供帮助。

代码匹配变量中的字符串,然后尝试将这些字符串写入文件(如果它们不存在于该文件中)。

代码不起作用。有什么帮助吗?

#this works
str_match = re.findall(r'(https?://[^\s]+)', input
if str_match:
    with open (datestamp+_"strings.txt", "a+") as text_file:
        for string in str_match:
            #THIS DOES NOT WORK -- WITH OR WITHOUT THE '\n'
            #WITH, ALWAYS SAYS IT EXISTS AND WRITES NOTHING
            if (string + '\n') in text_file:
                print "str exists"
            else:
                print "Doesn't exist"
                text_file.write(string + '\n')

没有它,它表示字符串不存在并将其多次写入文件。

if string in text_file:
                print "str exists"
            else:
                print "Doesn't exist"
                text_file.write(string + '\n')

如果我查看使用vim编写的字符串,它看起来像:mystring $

($附加在每个字符串的末尾 - 不,添加 +" $" 不起作用)

请帮忙吗?

2 个答案:

答案 0 :(得分:3)

这里的问题是文件没有(真的)支持in运算符的成员资格测试。

没有抛出错误的原因是因为文件是可迭代的,因此x in file计算为any(x is e or x == e for e in file)docs)。此操作只能运行一次,因为在第一次文件耗尽之后,不再能读取任何行(直到您编写新行)。

问题的解决方案是将文件中的所有行读入列表或集合并将其用于成员资格测试:

all_lines= set(text_file)
...
if (string + '\n') in all_lines:

但是,这并不能解释为什么if (string + '\n') in text_file:始终返回True。实际上它应该总是(在第一次迭代之后)返回False,这正是我在我的机器上运行代码时发生的事情。可能会在代码的其他部分写入文件。

答案 1 :(得分:2)

问题是你正在迭代文件一次,然后文件没有倒回。文件只扫描一次。

你必须首先将数据读入set,然后你可以遍历字符串(set非常高效,因为在O(log(N))中使用二分法搜索)

问题:如果str_match中有重复项,则会多次写入,因此我添加了set

的单一性
if str_match:
    with open(datestamp+"_strings.txt", "r") as text_file: # read-only
        lines = set(map(str.rstrip,text_file)) # reads the file, removes \n and \r
    with open(datestamp+"_strings.txt", "a") as text_file: # append, write only
        for string in set(str_match):
            #THIS DOES NOT WORK -- WITH OR WITHOUT THE '\n'
            #WITH, ALWAYS SAYS IT EXISTS AND WRITES NOTHING
            if (string) in lines:
                print("str exists")
            else:
                print("Doesn't exist")
                text_file.write(string + '\n')

注意:

  • 要保留文件中的顺序,请在set循环中删除for string,然后在找到时将字符串添加到lines
  • 添加了\n的第一个版本在Linux上运行正常,但在Windows上它会因\r而失败。现在,当我将它们放入迷你数据库时,我rstrip行:在测试时无需添加\n并且可移植
  • 解释了您在vim中看到的string$:vim在显示文本时将行尾添加为$。神秘解决了。