如果我理解您的意思,并且您想获取按频率排序的项目列表,则可以通过以下方式进行管道传输:
| sort | uniq -c | sort -k1nr
例如:
输入:
file1
file2
file1
file1
file3
file2
file2
file1
file4
输出:
4 file1
3 file2
1 file3
1 file4
更新
顺便说一句,你用 awk 做什么?
find . -name 'quest*' | cut -d_ -f1 | sort | uniq -c | sort -k1nr | head -n10
返回更经常找到的 10 个项目。
更新
这是一个大大改进的版本。唯一的缺点,它不是按出现次数排序的。但是,我将弄清楚如何解决它:)
find . -name 'question*' | sort \
| sed "s#\(.*/question\([0-9]\+\)_[0-9]\+\)#\2 \1#" \
| awk '{ cnt[$1]++; files[$1][NR] = $2 } END{for(i in files){ print i" ("cnt[i]")"; for (j in files[i]) { print " "files[i][j] } }}'
更新
在对约 140 万条记录进行测试后(花了 23 英寸),我认为 awk 效率太低,无法处理所有分组等内容,所以我用 Python 编写了它:
#!/usr/bin/env python
import sys, re
file_re = re.compile(r"(?P<name>.*/question(?P<id>[0-9]+)_[0-9]+)")
counts = {}
files = {}
if __name__ == '__main__':
for infile in sys.stdin:
infile = infile.strip()
m = file_re.match(infile)
_name = m.group('name')
_id = m.group('id')
if not _id in counts:
counts[_id] = 0
counts[_id]+=1
if not _id in files:
files[_id] = []
files[_id].append(_name)
## Calculate groups
grouped = {}
for k in counts:
if not counts[k] in grouped:
grouped[counts[k]] = []
grouped[counts[k]].append(k)
## Print results
for k, v in sorted(grouped.items()):
for fg in v:
print "%s (%s)" % (fg, counts[fg])
for f in sorted(files[fg]):
print " %s" % f
它完成了拆分、分组和排序的所有工作。在同一个输入文件上运行只需要大约 3 英寸(添加了所有排序的东西)。
如果您需要更快的速度,可以尝试使用 Cython 进行编译,这通常至少快 30%。
更新 - Cython
好的,我刚尝试过 Cython。
只需将上述文件另存为calculate2.pyx
. 在同一文件夹中,创建setup.py
:
from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = [Extension("calculate2", ["calculate2.pyx"])]
)
还有一个启动器脚本(我命名它calculate2_run.py
)
import calculate2
import sys
if __name__ == '__main__':
calculate2.runstuff(sys.stdin)
然后,确保您已安装 cython,然后运行:
python setup.py build_ext --inplace
除其他外,这应该生成一个calculate2.so
文件。
现在,calculate2_run.py
像往常一样使用(只需输入 find 的结果)。
我在同一个输入文件上运行它,没有任何进一步的优化:这一次,它花了 1.99''。