Saya perlu mencari beberapa file log (semua file yang dihasilkan dalam 24 jam terakhir, semua disimpan di direktori yang sama) untuk menemukan kemunculan terakhir string. Ini adalah perintah yang saya tulis:
find . -mtime 1 | grep fileprefix | xargs grep 'search string' | tail -1
Tetapi ini hanya mengembalikan baris terakhir untuk satu file. Ada saran tentang cara men-tweak ini untuk mendapatkan semua baris?
bash
shell-script
text-processing
grep
Lokesh
sumber
sumber
Jawaban:
Dengan asumsi fasilitas GNU:
sumber
find
menjalankan perintah pada file menggunakan-exec
. Denganbash -c
, kami menelurkanbash
shell yang loop melalui file yang ditemukan olehfind
dan mengeksekusitac .. | grep -m1 fileprefix
pada masing-d" "
dengan potongan. Kutipan ganda alih-alih tunggalfind
perintah dapat menyaring untuk awalan berkas; yanggrep
seharusnya tidak diperlukan untuk itu. Mengejutkan juga bahwa string pencarian tidak menemukan jawaban ini.Jika semuanya ada dalam satu direktori, Anda dapat melakukan:
Jika ini adalah file besar, mungkin perlu mempercepat dengan menggunakan
tac
untuk mencetak file dalam urutan terbalik (baris terakhir terlebih dahulu) dan kemudiangrep -m1
untuk mencocokkan kejadian pertama. Dengan begitu, Anda menghindari harus membaca seluruh file:Keduanya menganggap tidak ada direktori yang cocok
fileprefix
. Jika ada, Anda akan mendapatkan kesalahan yang bisa Anda abaikan. Jika itu masalah, periksa hanya file:Jika Anda juga perlu nama file dicetak, tambahkan
-H
ke setiapgrep
doa. Atau, jika Andagrep
tidak mendukungnya, katakan juga untuk mencari/dev/null
. Itu tidak akan mengubah output tetapi karenagrep
diberikan beberapa file, itu akan selalu mencetak nama file untuk setiap klik:sumber
tac
. Itu akan keluar segera setelah pertandingan pertama ditemukan. Saya baru saja menguji dengan file teks 832M dan pola yang ditemukan pada baris terakhir.grep -m 1 pattern file
alat ~ 7 detik dantac file | grep -m1 pattern
butuh0.009
.... akan berfungsi jika Anda memiliki GNU
sed
yang mendukung-s
opsi file eparate dan POSIXfind
.Anda mungkin harus menambahkan
! -type d
atau-type f
kualifikasi, karena mencoba membaca direktori tidak akan sangat berguna, dan semakin mempersempit rentang ke file biasa dapat menghindari pembacaan tergantung pada pipa atau file perangkat serial.Logikanya sangat sederhana -
sed
menimpah
ruang lamanya dengan salinan dari setiap jalur input yang cocoksearchstring
, kemudiand
menghapus dari output semua jalur input tetapi yang terakhir untuk setiap file input. Ketika sampai ke baris terakhir, iax
mengubah ruang penahanan dan pola, dan jikasearchstring
ditemukan sama sekali saat membaca file, kejadian terakhir seperti itu akan dicetak ulang secara otomatis ke output, jika tidak maka akan menulis baris kosong. (tambahkan/./!d
ke ekorsed
skrip jika itu tidak diinginkan) .Ini akan melakukan
sed
doa tunggal per 65k beberapa file input - atau berapa punARG_MAX
batas Anda . Ini harus menjadi solusi yang sangat performan, dan cukup sederhana diimplementasikan.Jika Anda juga menginginkan nama file, diberikan GNU baru-baru ini
sed
Anda dapat menuliskannya ke baris yang terpisah denganF
perintah, atau Anda dapat membuatnya dicetak olehfind
dalam daftar terpisah per batch dengan menambahkan-print
primer setelahnya+
.sumber
Bagaimana tentang:
Di atas memberikan Anda hasil yang bagus dengan kemunculan terakhir dari string pencarian di setiap file diikuti oleh nama file masing-masing setelah koma (memodifikasi bagian ", $ 1" di bawah gema untuk mengubah format atau menghapusnya jika tidak perlu). Contoh output yang mencari string pencarian '10' dalam file dengan awalan nama "file" adalah sebagai berikut:
sumber
Ini menggunakan GNU
grep
's-H
dan-n
pilihan untuk selalu mencetak kedua nama file dan linenumber dari semua pertandingan, maka macam oleh nama file dan linenumber, dan pipa ke awk, yang menyimpan pertandingan terakhir untuk setiap nama file dalam array, dan akhirnya mencetak Itu.Metode yang cukup kasar, tetapi berhasil.
sumber