【发布时间】:2020-10-14 06:10:21
【问题描述】:
$var 包含数千行,格式如下:
./abc bbd xyh doc
./docs 2019 abc docx
./docs 2019 abc docx
./docs 2019 abc ppt
./docs 2019 abc ppt
./docs 2019 abc xls
./docs 2019 abc def docx
./docs 2019 abc/def docx
./bdg/aabc/dd efgh 2018 doc
. xls
. pptx
./aax bcd/def/gfhe ttp/five ppt
最后一列代表文件的extension,其他所有内容(从每一行的开头,直到最后一个空白字符)都是相应文件的basename(路径)。
有一个while循环为$path生成值,其中包含一个测试basename(路径),我的目标是从$var中删除所有与$path不匹配的行,从开头开始行直到最后一个空格(不包括最后一列)。此外,我只想打印相应的扩展名(如| sort | uniq -c)。
例如,如果在 while 循环的迭代过程中我们发送 path="./docs 2019 abc",则输出应该是最快的方式来实现以下目标:
2 docx
2 ppt
1 xls
这是我最终得到的结果,但输出是错误 - 它打印的是基本名称,而不是扩展名,而且每次迭代都很慢:
printf "echo -e \"%s\" | awk '{\$NF=\"\";} ( \$0 ~ /%s/ )' | sort | uniq -c | sort -k1 -nr" "${var}" "${path//\//\\/}" | bash
输出:
2 ./docs 2019 abc
2 ./docs 2019 abc
1 ./docs 2019 abc
【问题讨论】:
-
$var contains thousands of lines对任何问题来说都是一个糟糕的开始。为什么你有一个包含数千行的标量变量?几乎可以肯定,您的代码中有一些较早的步骤应该被修复,这样您就不会处于这种情况。 -
@EdMorton:完全是我的想法。
$var是相当复杂的find命令的输出。为了避免对所有子目录嵌套如此复杂的find,我形成了包含整个输出的$var。有什么更好的方法来做到这一点?附言甚至每个子目录的递归(嵌套)find -maxdepth 1都比这个恕我直言更快。 -
将它们保存到临时文件中如何?
-
@oguzismail:可以做到。您认为这种方法是正确执行此操作的最快方法吗?
-
我进一步调查了这个问题,看看是否切换到使用文件而不是在变量中存储大量数据。似乎 bash 变量可以保存多少数据没有限制,除了操作系统设置的任何内容。但是,我可以使用
mkfifo,如果/tmp是tmpfs挂载,而且通常是这样,那么无论如何它都会使用内存。嗯.. 看来性能方面我在这里没有做错任何事情(将大量数据存储在变量中)?唯一严重的瓶颈似乎是对其进行多次排序,但@oguzismail 已经为它提供了一些解决方法。