从高到低,这是我的看法...
为什么这很不完美且困难?因为尽管你很勤奋地改进了问题,但它仍然有很多未定义的地方,而且已经相当复杂了。幸运的是,其他人也研究过文本文件,并开发了整个编程语言来处理它们。但即使你已经彻底学习了其中一些,你仍然会受到影响,因为按照你的规范操作的计算机非常愚蠢。快速,但愚蠢。
对于像findstr、egrep这样的开箱即用的工具来解决这个特定的问题,对我来说几乎是不可能的。像Python这样的编程语言更加可行和具有未来性。
因此,编程任务分为两个部分:
- 遍历目录树以访问每个文件
- 在每个文件的内容中查找列表
至于后者,正则表达式看起来像是一种可行的机制,但首先要问的问题是,你能负担得起它们吗?显然我们需要多行处理,每当我见到这样做时,都是一次性处理整个文件。你能负担得起将整个文件读入内存吗?你能负担得起从磁盘读取整个文件吗——也许头部在文件顶部,读取整个主体是浪费的?我假设没有问题。
使用单个正则表达式直接从文件中提取单个附件名称似乎非常复杂(即使在支持重复捕获的语言中)。因此,我会让一个正则表达式先找到列表,然后再将其分割。甚至不考虑你所说的.txt文件是什么意思,以及测试用例太少的情况下,这就带我们到了:
import os
import re
searcher = re.compile(r"^Attachments: (.+?)^---+$", flags=re.MULTILINE+re.DOTALL)
def visitFile(filepath, out):
with open(filepath) as f:
match = searcher.search(f.read())
if match:
for name in match.group(1).split('\n')[:-1]:
out.write("%s\t%s\n" % (filepath, name))
def visitFolder(topdirpath, out):
for dirpath, subdirnames, filenames in os.walk(topdirpath):
subdirnames.sort()
filenames.sort()
for filename in filenames:
visitFile(os.path.join(dirpath, filename), out)
if __name__ == "main":
visitFolder(sys.argv[1], sys.out)
import io
import tempfile
import unittest
class FolderBasedTestCase(unittest.TestCase):
def setUp(self):
self.tempdir = tempfile.TemporaryDirectory(prefix="test_dir_")
self.out = io.StringIO()
def tearDown(self):
self.tempdir.cleanup()
self.out.close()
def walkthewalk(self):
visitFolder(self.tempdir.name, self.out)
class EmptyFolderTestCase(FolderBasedTestCase):
def runTest(self):
self.walkthewalk()
self.assertEqual(self.out.getvalue(), "")
class FriendTestCase(FolderBasedTestCase):
def setUp(self):
super().setUp()
with open(os.path.join(self.tempdir.name, "friend"), "w") as f:
f.write("Some: Stuff\n" +
"Attachments: Purely Practical.pdf\n" +
"Daily Revenue.xls\n" +
"Advertising_Ideas.doc\n" +
"-------------\n" +
'From: "Mouse, Mickey" Mickey.Mouse@mouseclick.com\n')
def runTest(self):
self.walkthewalk()
self.assertEqual(self.out.getvalue().replace(self.tempdir.name + os.sep, "{p}"),
"{p}friend\tPurely Practical.pdf\n" +
"{p}friend\tDaily Revenue.xls\n" +
"{p}friend\tAdvertising_Ideas.doc\n")
class FooTestCase(FolderBasedTestCase):
def setUp(self):
super().setUp()
with open(os.path.join(self.tempdir.name, "foo"), "w") as f:
f.write("From: your worst enemy\n" +
"\n" +
"Mail body here. This week's topics:\n" +
"Attachments: are't they a pain?\n" +
"Pain: don't we get attached to it?\n" +
"\n")
def runTest(self):
self.walkthewalk()
self.assertEqual(self.out.getvalue(), "")
请注意,正则表达式(希望如此)与文件的换行符无关,但是目前的split()
需要正确的行分隔符。
我怀疑编译和单独存储正则表达式是否有任何性能优势,任何人都不会注意到,但我认为对于这个小代码量,它实际上使事情更易读。
要运行单元测试,特别是如果您将代码和测试用例存储在单个文件scriptname.py中,请执行`python -m unittest scriptname'。
re
更适合这个。 - Monacraft