文字列の最後の出現を見つけるには、複数のログファイル(過去24時間に生成されたすべてのファイル、すべて同じディレクトリに保存されている)を検索する必要があります。これは私が書いたコマンドです:
find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1
しかし、これは1つのファイルの最後の行のみを返します。これを調整してすべての行を取得する方法に関する提案はありますか?
GNUファシリティ:
find . -mtime -1 -exec bash -c \
'for f; do tac "$f" | grep -m1 fileprefix; done' _ {} +
すべてが単一のディレクトリにある場合は、次のようにすることができます。
for file in *fileprefix*; do
grep 'search string' "$file" | tail -1
done
これらが大きなファイルである場合は、tac
を使用してファイルを逆の順序で(最後の行を最初に)印刷し、次にgrep -m1
を使用して最初の出現と一致させることで、速度を上げる価値があります。これにより、ファイル全体を読み取る必要がなくなります。
for file in *fileprefix*; do
tac file | grep -m1 'search string'
done
どちらもfileprefix
に一致するディレクトリがないと想定しています。存在する場合は、無視できるエラーが表示されます。問題がある場合は、ファイルのみを確認します。
for file in *fileprefix*; do
[ -f "$file" ] && tac file | grep -m1 'search string'
done
ファイル名も印刷する必要がある場合は、各grep
呼び出しに-H
を追加します。または、grep
がサポートしていない場合は、/dev/null
も検索するように伝えます。出力は変更されませんが、grep
には複数のファイルが指定されているため、ヒットごとに常にファイル名が出力されます。
for file in *fileprefix*; do
grep 'search string' "$file" /dev/null | tail -1
done
find . ! -name . -Prune -mtime 1 -name 'fileprefix*' \
-exec sed -se'/searchstring/h;$!d;x' {} +
... GNU sed
が-s
eparate filesオプションとPOSIX find
をサポートしている場合に機能します。
ただし、! -type d
または-type f
修飾子を追加する必要があります。ディレクトリを読み取ろうとしてもあまり役に立ちません。通常のファイルに範囲をさらに狭めると、パイプまたはシリアルデバイスでの読み取りのハングを回避できます。ファイル。
ロジックは非常にシンプルです。sed
は、h
に一致する入力行のコピーでsearchstring
oldスペースを上書きし、次にすべての入力行を出力からd
eletesします。各入力ファイルの最後。最後の行に到達すると、e x
はそのホールドスペースとパターンスペースを変更します。そのため、ファイルの読み取り中にsearchstring
が見つかった場合、最後に発生したものが自動出力されて出力されます。空白行を書き込みます。 (望ましくない場合は、sed
スクリプトの末尾に/./!d
を追加します)。
これは、いくつかの65k入力ファイルごとにsed
を1回呼び出すか、またはARG_MAX
の制限が何であっても実行します。これは非常にパフォーマンスの高いソリューションであり、非常に簡単に実装できます。
ファイル名も必要な場合は、最近のGNU sed
を指定すると、F
コマンドを使用して別の行に書き出すことができます。 -print
の後に+
プライマリを追加することにより、バッチごとに別のリストでfind
によって印刷されます。
どうですか:
find . -mtime -1 -name "fileprefix*" -exec sh -c \
'echo "$(grep 'search string' $1 | tail -n 1),$1"' _ {} \;
上記は、各ファイルで最後に検索文字列が出現し、その後にコンマの後にそれぞれのファイル名が続く素敵な出力を提供します(エコーの下の "、$ 1"の部分を変更してフォーマットを変更するか、不要であれば削除します)。 「file」という名前の接頭辞が付いたファイルで「10」の検索文字列を検索するサンプル出力は次のとおりです。
[dmitry@localhost sourceDir]$ find . -mtime -1 -name "file*" -exec sh -c 'echo "$(grep '10' $1 | tail -n 1),$1"' _ {} \;
Another data 02 10,./file02.log
Some data 01 10,./file01.log
Yet another data 03 10,./file03.log
find . -mtime 1 -name 'fileprefix*' -exec grep -Hn 'search string' {} + |
sort -t: -k1,2 -n |
awk -F: '{key=$1 ; $1="" ; $2="" ; gsub(/^ /,"",$0); a[key]=$0}
END {for (key in a) { print key ":" a[key] }}'
これはGNU grep
の-H
および-n
オプションを使用して、常にすべての一致のファイル名と行番号の両方を出力し、次にファイル名とlinenumber、それをawkにパイプし、各ファイル名の最後の一致を配列に格納し、最終的に出力します。
かなり力ずくの方法ですが、機能します。