我想使用Nu打开几个 Excel 文件,在其中搜索文本并打印每个匹配的行及其位置。例如:
Hugh file.xsls,第 123 页,第 98765 行:... 待办事项 ...
要打开单个文件,我尝试了:
open "huge file.xlsx" | find todo
但结果是一行包含整个 Excel 文件作为一个(JSON?)字符串。我发现 Nu 可以打开 Excel 文件非常有帮助。我只需要一种方法来获得更好的搜索结果显示。:-)
这个问题是关于 Nu,而不是任何其他可以实现这一目标的 shell、编程语言或工具。:-)
这里的主要问题是 Nushell 的
find
机制不能与电子表格的嵌套表结构“很好地配合”。该find
命令接收的open "huge file.xlsx"
只是 Excel 文件中每个工作表(选项卡)的一行。它很高兴地扫描该行,找到文本,是的,将每个工作表作为一个结果集返回。它不完全是 JSON,甚至也不完全是 Nuon;
find
我猜想可能只是面对嵌套表时内部结果的一些副作用。有几种可能的方法可以从
find
Excel 文件中获得更好的结果。然而,这些方法的效率都不是很高,因为它们涉及多次扫描文件。你说文件“巨大”,但大小是相对的,所以我不太确定这意味着什么。我在这里假设该文件不会太大而无法加载到内存中。通过在执行以下操作之前将其加载到内存中,性能似乎与“正常”的单个find
.简单(?)的解决方案
首先,这是一个通用的 Nu 解决方案,可以维护现有的
find
功能。为了简洁起见,我在一个较小的文件1上运行它(sample.xlsx
如下所列),我的搜索词是foo
:结果见下文脚注2。
选择
返回更接近您问题中的示例的结果的替代解决方案稍微复杂一些。本质上,我们需要“展开”每个嵌套层并分别扫描最终结果,以便识别:
...它被发现的地方。
对可能“棘手”的关键点的解释:
enumerate
对该列进行计算,以便我们知道删除不匹配行后的行号find
编辑文本index
(由 提供的行号enumerate
)each
语句都会创建自己的表,因此最后,我们需要为每个循环flatten
获取一次结果。each
结果更加紧凑(但仍然是 Nu 表):
当然,完全可以基于上面的Nushell字符串插值来输出文本。
虽然我还没有走到这一步,但如果您想获得一些“上下文”(每个找到的结果之前和之后的文本),您可能会使用某种形式来修剪结果
str replace
。表现
我还在一个更大的文件上对此进行了测试。我在 Excel 文件中拥有约 15,0000 个 Stack Overflow 答案(包括其 Markdown),用于研究潜在的 ChatGPT/AI 答案。我基本上在几张表中复制了 15k 行,最终在 20MB 文件中得到了超过 100k 行。我不认为这是“巨大的”,但它是实质性的。无独有偶,它也包含了很多带有“todo”这个短语的答案。
...仅用了 15 秒多一点(使用
timeit
命令)就返回了 945 个结果。这与正常的find
. 但是,如果每次都从磁盘读取文件(而不是提前加载到内存中),则扫描只需 1 分钟多一点。脚注
1
sample.xlsx
:Sheet1:空
表2:
表3:
2第一个命令的结果:
注意:该命令会突出显示所有“foo”
find
找到的内容,但这些在 Markdown 中不可见: