Günlük dosyasından parça nasıl kesilir?


18

8 Gb günlük dosyam var (Rails üretim günlüğü). Bazı tarihler (satırlar) arasında kesmem gerekiyor. Bunu yapmak için hangi komutu kullanabilirim?


1
Hey millet, bu soru büyük bir dosya hakkında, bu yüzden "Ante up!" .. zaman önemlidir ... 85904064 satır (satır başına 100 karakter) ile gerçek bir 8 GB dosya üzerinde tercih sed komut dosyası test ettim. Sed'i seviyorum, ancak durduğu gibi, sed komut dosyası her seferinde tüm dosyayı tarar . Bu ortalama bulduğunda çıkan awk betiğinin iki katı kadar yavaş yapar ... Sanırım (?) Sed betiğinin ikinci ifade için d yerine sadece aq'ye ihtiyacı olabilir ... Test sonuçları burada: yapıştır .ubuntu.com / 573477 .. Ayrıca, doğru çıktı üretmiyor .. sonunda asoundmove cevabında benim yorum bakın.
Peter.O

asoundmove'un yeni sed sürümü hız sorununu ele almıştı ve şimdi awks'in hızıyla eşleşiyor. ve yeni versin şimdi verileri doğru çıktılar ... daha fazla ayrıntı için yorumlarına bakın.
Peter.O

Sadece "kes" dediğini fark ettim. .... Eğer "kesim" demek istediyseniz, o sedzaman kolayca yapacağız.
Peter.O

Yanıtlar:


12

Gibi bir şey

sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less

tee cut-logdosyaya nelerin konulduğunu görmenizi sağlar cut-log.

DÜZENLE:

Fred.bear'ın titiz standartlarını karşılamak için işte bir sed çözümü (tartışmasız awk çözümü çok daha güzel olsa da):

b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"


3
@dogbane: evet, evet. Düzenlenen. Eminim bazen optimal koddan daha az yazarsınız, bu kadar sert bir yorumu hak ediyor mu?
asoundmove

1
not: Aynı tarihe sahip birden fazla ardışık 'ilk tarih' satırı varsa, ilk olanlar hariç tümü silinmeyecek ve çıktıya tanıtılacaktır ... sadece farkında olması gereken bir şey ... durum)
Peter.O

1
... ama bir profesyonel sed ++ olsa bile, bu özel işin kendi kişisel aracı dışında herhangi bir şey için sınırlarının ötesinde olduğunu düşünüyorum .. İşte sed bu durumda (sizin ve benim .. seninle aynı yapmak için sed almak başardı .. o da% 1 içinde koştu) .. geri ana konu .. (hangi awk için geçerli değildir) .... Hata (düzeltilemez): Günlük kapsamında geçerli olan ancak günlükte bulunmayan bir tarihle ilgili olarak, 1. arg durumunda sed'in hiçbir şey yazdırmamasına neden olur ve 2. arg durumunda sed her şeyi yazdırır ilk tarihten sonra! ... devamı ...
Peter.O

1
Başka bir düzeltilebilir hata: Şu anda veri oranı da dahil olmak üzere herhangi bir satırdaki tarihlerle eşleşiyor mu, ancak bu sadece bir normal ifade tweak .. Ve bunu kullanmak isteyen herkes için, belki de argümanların şimdi ilkine atıfta bulunduğunu ve aralıktaki son tarihler (-1 ve +1 değil) .. ve son olarak .. "titiz standartlar" benim değil. Ben sadece Sorgulayanlar talebinin elçisiyim ... Kullanıcı istendiği gibi çalışıp çalışmadığını fark edecektir .. Bu benim için harika bir soru .. Çok şey öğrendim :) ... ve memnunum hız ile sedeşleşebileceğini bilmek awkve aslında biraz daha hızlıydı.
Peter.O

6

FOO ve BAR dahil her şeyi yazdırmak için şunu deneyin:

$ sed -n '/FOO/,/BAR/p' file.txt

1
not: Bu sadece ardışık BAR serisinin ilk
BAR'sini basacaktır

başka bir not ... Verilerinde tarihlerden biri yoksa büyük sorun .. Son tarih mevcut değilse sed, EOF'a ulaşana kadar satırların çıktısını almaya devam edecektir.
Peter.O

5

Bu istediğinizi yapacak ...
Parametre tarihlerini Dahil Etme ve Hariç Tutma gösterilir.

# set Test args
set  2011-02-24  2011-02-26  "junk"

from="$1"
till="$2"
file="$3"

# EITHER ====                              +++++++++  
# Ouptut lines between two parameter dates INCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 >= from) && ($2 <= till) { print $0 ; next }
    ($2 > till) { exit }' "$file"

# OR ========                              ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
  awk -v from=$from -v till=$till '
    ($2 > from) && ($2 < till) { print $0 ; next }
    ($2 >= till) { exit }' "$file"

Alan 2'de (sıralı) bir tarihi test eder ... İşte test verileri için bir örnek

    98  2011-02-05 xxxx
    99  2011-02-05 xxxx
   100  2011-02-06 xxxx
   101  2011-02-06 xxxx

Ve işte test veri üreteci .


Ben (örneğin ilkini alarak) biraz daha basit awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
yazacaktı

@asoundmove: Evet, bu daha iyi görünebilir ve kesinlikle daha gelenekseldir , ancak gerçekte, yürütme süresi toplamda sadece 1 ekstra ififadenin süresi (hatta satır başına 1 değil) yani. mantık akışı etkili bir şekilde aynıdır ve çalışma süresindeki fark nanosaniye cinsinden sayılır. "Başka" kullanmamamın tek nedeni, bu benim ilk senaryom (bir gün 4 yıl dışında) önce bazı örneklerle oynadığımda) ... ve bulduğum ilk uygulanabilir dal mekanizması ... (ve belirtildiği gibi. bu kadar hızlı) .. Genellikle Tryawksedq
Peter.O

Bu yöntemde metin dosyası adını ve konumunu nereye verdiğinizi anlamıyorum? Birisi aptallığımı görmeme yardım edebilir mi
Giles

4

Günlük dosyanızda bu biçimde tarihler varsa, YYYY-MM-DDörneğin 2011-02-10 için tüm girişleri bulmak için şunları yapabilirsiniz:

grep 2011-02-10 log_file

Şimdi, 2011-02-10 ve 2011-02-11 için girişleri bulmak istiyorsanız, tekrar kullanın, grepancak birden çok desenle kullanın :

grep -E '2011-02-10|2011-02-11' log_file

İyi. "Reklamı grepyapıldığı gibi" çalışır :) ... Ancak, tarih aralığı dosyanın başında olsa bile dosyanın tamamını arar . Ortalama olarak, bu, aramanın süresini "aralıktaki son öğeden sonra çıkış" ile karşılaştırıldığında iki katına çıkarır ... Bunu yalnızca, 8 GB dosya boyutunda, grep süresi sonuçları buradaki sed örneğiyle hemen hemen aynıdır (1dk 58sn). Benim zaman testler sonuçları link: paste.ubuntu.com/573477
Peter.O

1

Bu boyuttaki dosyalarla çalışmak her zaman zordur.

Bir yol bu dosyayı birkaç küçük dosyaya bölmek olabilir, bunu yapmak için split komutunu kullanabilirsiniz.

split -d -l 50000 ToBigFile.data file_

Bölünmüş olsanız bile, hala bir bash for loop kullanarak bir dosya gibi çalışabilirsiniz

for f in `ls file_*`; do cat $f; done;

Ancak kedi yerine, istenmeyen verilerden kurtulmak için ters grep kullanabilirsiniz, bunun için önemsizdir. (veya ihtiyacınız olan ayrıntılandırma türünü).

Bu noktada sadece çok daha küçük dosyalarla çalışacaksınız ve yukarıda belirtilen diğer komutlar çok daha küçük dosyalarda daha sorunsuz çalışacaktır.

Ve işiniz bittiğinde, yeni küçük dosyayı tekrar oluşturmak için bir saniye döngü kullanabilirsiniz.

for f in `ls file_*`; do cat $f >> NewFile.data ; done;

Güncelleme Verileri birden fazla dosyaya bölmeye başladığımızdan beri, sabit sürücüde çok fazla iş olacak ve bu da zaman alıyor. (Bu soruda görünüşe göre 5dk).

Öte yandan, sonraki adımlar muhtemelen daha hızlı olacaktır.

Yani bu yöntem muhtemelen basit grep, awk, sed işlemi için anlamsızdır, ancak arama desenleri daha karmaşık hale gelirse daha hızlı olabilir.


3
Johanm, bilgisayarımda 8 GB günlük dosyasını aramak ortalama olarak sadece 1 dakika sürer ve aynı bilgisayardaki, sadece inital dosya bölme işlemi 4 dakika 43 saniye sürer ... :)
Peter.O

Diyelim ki daha küçük dosyalarda bu garip ve sed sürelerini% 50 oranında azaltabiliyorsunuz. Daha sonra toplam süreye ulaşmadan önce bu operasyonun 10'dan fazlasını yapmalıyız ... Belki de dosya bölünmesi birkaç gerileme için en iyi fikir değildir ...
Johan

Awk betiği (kolayca) 10 dosyaya 10 farklı arama sonucu çıkarmak için değiştirilebilir ... tek bir geçişte, ama aslında raporları çıktılarken okumayı yavaşlatır ... Sed de aynı şeyi yapabilirdi, ama ben Asoundmove'un yorumlarında bahsetmişseniz, sed, belirli bir tarih / saatin günlüğe girmemesi durumunda başarısız olur (örneğin, saate göre arama yapıyorsunuz) .. sed'i çok kullanıyorum ve son derece yararlı, ancak sınırları var ... Burada sed vs awk ne zaman kullanılacağına dair bir SSS var ... Her şeyle aynı fikirde değilim, ama ne anlama geldiğini görebiliyorum ... sed.sourceforge.net/sedfaq6.html
Peter. Ey

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.