1

それぞれがファイルを含む多くのサブディレクトリを含むディレクトリを検索する必要があります。ファイルは次のように読み取られます。question1234_01、ここで1234はランダムな数字で、接尾辞_01はプレフィックスを含むメッセージの数であり、同じ継続スレッドの一部であることを意味します。

find . -name 'quest*' | cut -d_ -f1  | awk '{print $1}' | uniq -c | sort -n  

出力例:

1 quest1234    
10 quest1523

これにより、すべてのファイルが検索され、順番に並べ替えられます。

私がやりたいのは、最も多く出現するファイルをすべて印刷することです。私の例では、一致するファイルが10個あります。

したがって、。quest1523_01を介してのみ出力する必要がありますquest1523_11

4

3 に答える 3

1

私があなたの意味を理解していて、頻度でソートされたアイテムのリストを取得したい場合は、次のようなものをパイプでつなぐことができます。

| 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インチかかりました。

于 2012-10-14T21:38:33.243 に答える
0

あなたはこのようなことをすることができます:

  1. 最初の検索結果を一時ファイルに保存します。
  2. ファイル数が最も多いプレフィックスを除外します
  3. その一時ファイルでプレフィックスを検索してから、一時ファイルを削除します

find -name 'quest*' | sort -o tempf
target=$(awk -F_ '{print $1}' tempf\
         | uniq -c | sort -n | tail -1\
         | sed 's/[0-9]\+ //')
grep "$target" tempf
rm -f tempf

ノート:

  1. 同じプレフィックスを持つファイルは同じサブディレクトリにあると仮定しました。
  2. 出力には、現在のディレクトリからの相対パスが含まれます。ベース名だけが必要な場合は、次のようsed 's/.*\///'にします。grep
于 2012-10-15T13:16:24.410 に答える
0

あなたの解決策はファイルのベース名を選択することではありませんが、私はあなたが探していると思います:

awk 'NF{ b=$(NF-1); v[b]=v[b] (v[b]?",":"") $NF;  a = ++c[b]} 
    a > max {max = a; n=b }  
    END {split(v[b],d, ","); for(i in d) print b "_" d[i]}' FS='[/_]'

データを並べ替える必要はありません。完全なソートは非常に高価です。

于 2019-05-21T10:09:53.330 に答える