Linux üzerinde bir günlük dosyası XML bloğunu nasıl ayıklanır

3 Cevap php

Ben aşağıdaki gibi görünen bir log dosyası var:

2010-05-12 12:23:45 Some sort of log entry
2010-05-12 01:45:12 Request XML: <RootTag>
<Element>Value</Element>
<Element>Another Value</Element>
</RootTag>
2010-05-12 01:45:32 Response XML: <ResponseRoot>
<Element>Value</Element>
</ResponseRoot>
2010-05-12 01:45:49 Another log entry

Ne yapmak istiyorum istek ve Tepki XML ayıklamak (ve sonuçta kendi tek dosyalara koyucak) 'dir. Ben egrep kullanılan benzer bir ayrıştırıcı vardı ama XML, tek bir satır yukarıdaki gibi birden fazla olanlar değildi.

Günlük dosyaları 500-600 megs bir günlük vurmak, ayrıca biraz büyük. Küçük günlükleri bir PHP komut dosyası aracılığıyla okumak ve regex eşleştirme kullanabilirsiniz, ancak böyle büyük bir dosya için gerekli bellek miktarı fazla muhtemel senaryoyu öldürmek olurdu.

Birden hatları ayıklamak ya da ben kabullenmesini ve ayıklamak için tüm dosya okumak için Perl ve PHP kullanmak zorunda gidiyorum bir Linux kutusu üzerinde yerleşik araçlar (bu durumda CentOS) kullanarak kolay bir yolu var mı?

3 Cevap

# Example usage:
# perl script.pl data.xml RootTag > RootTag.xml

use strict;
use warnings;

my $tag = pop;

while (<>){
    if ( s/.*(<$tag>)/$1/ .. s/(<(\/)$tag>).*/$1/ ){
        print;
        last if $2;
    }
}

Hakkında ayrıntılı bilgi için dokümanlar bakın flip-flop operator.

sed (Öyle SuperSed söylemek için cazip bir iş gibi geliyor ;-)

sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</</;x;p}; ${x;p}' xmllog

burada xmllog log dosyasının adıdır. Sen başında boş bir satır alırsınız, ama o egrep '.+' hatta sadece tail -n +2 ile filtre edilebilir.

Açıklama yoluyla, sed eşleşen koşulları ve ilgili eylemlerin listesi oluşur programları için biraz tercüman. sed hattı ile bir dosya hattı (bu nedenle adı "stream editor" -> "sed") üzerinden çalışır ve her bir hat için, çizgi üzerinde metin maçlar programda her bir durum için, bu geçerlidir karşılık gelen eylem. Bu durumda:

/^<.\+>/

(\+) {[(izledi < herhangi bir karakteri (.), bir veya daha çok kez tekrarlanan izledi içeren herhangi bir satır eşleşen bir düzenli ifade durumdur 3)]} - temelde bir XML etiketi ile herhangi bir hat. Ilişkili eylem bir "tampon tutun" satırını ekler H hangi. Diğer bir durumdur

/\(Request\|Response\) XML/

, tabii ki, ya da Request ya da Response ve ardından bir boşluk ve XML ile eşleşen bir sıradanifade olan. Karşılık gelen eylem

{s/^.*</</;x;p}

ki birinci (^) (.), herhangi sayıda ({[tekrarlanan herhangi bir karakter ile (s) satırın başında bir ikame takip etmez (3)]}) sadece < ile < eklenmiştir. Temelde bu hat üzerinde ilk XML etiketinden önce bir şey kurtulur. Sonra (x) hat sadece "tampon tutun" (önceki günlük mesajın XML içeren) ve sadece takas edildi baskılar (p) malzeme ile okuma anahtarları tutun tampon içinde. Son olarak,

$

girdi sonunu eşleşir ve {x;p} yine sadece "baskı tampon" içine tutun tampon içeriğini değiştirir ve sonra yazdırır.

Eğer farklı kayıtları sınırlandırmak için bir şey gerekirse sizin ihtiyaçlarınıza uygun komutu değiştirebilir, örneğin, bu aralarında bir satır boşluk koymak gerekir:

sed -n '/^<.\+>/H; /\(Request\|Response\) XML/{s/^.*</\n</;x;p}; ${x;p}' xmllog

(Bu durumda, elbette, egrep başında boş satır filtrelemek için kullanmayın).

Sorunuzu doğru düşünmüyorsun ima; Eğer bir dil (vardır) içinde ne soruyorsun yapmak için bir yolu varsa ... o zaman herhangi bir dilde bunu yapabilirsiniz.

Belleğe günlüğün tamamını okumak için hiçbir neden yok. Sadece satır satır okumak ve istediğiniz bilgileri ayıklamak. Sen sadece (değil etiketinde, RootTag içeride, ResponseRoot inside, vb) nerede olarak bir devlet tutmak gerekir ve istediğiniz gibi verileri işlemek.