Franz Napisano Luty 28, 2008 Zgłoszenie Share Napisano Luty 28, 2008 Witam ! Od jakiegoś czasu borykam się z problemem zoptymalizowania porównywania poszczególnych linii. Dane w tych liniach (wierszach) są rozdzielone przecinkami. Najprostrze rozwiązanie polegające na dwóch pętlach 'for', z których jedna wyciąga wiersz, a druga przemiata i porównuje odpowiednie pola rozdzielone przecinkami, okazuje się być troche nieoptymalne, ponieważ chcąc porównać pliki które mają np. po 300 linii i wypisać różniące się pola, możemy iść zrobić sobie kawe a maszyna wskazuje Load Average na poziomie >1.. Pytanie proste.. czy jakaś bardziej doświadczona osoba ode mnie mogłaby naprowadzić mnie na rozwiązanie dające lepsze czasy i mniejsze Load Average ? Podejrzewam, że odpowiednia składnia AWK lub SEDa pewnie potrafi polepszyć te parametry i zrobić to o wiele wydajniej.. Swoje rozwiązanie prezentuje poniżej: baza=/home/baza.csv temp=/home/temp.csv while read linia;do host=`echo $linia | cut -d "," -f13` linia1=`grep $host $baza` #linia w tempie do przejrzenia for((i=1; i<=LIM; i++));do a=`echo $linia | cut -d "," -f$i` #wlasciwe linie z tempa b=`echo $linia1 | cut -d "," -f$i` #linie z bazy c=`echo $linia | cut -d "," -f13` if [ "$host" == "$c" ];then if [ "$a" != "$b" ];then f=1 break else f=0 fi fi done if [ $f -eq 1 ];then echo echo $c echo fi for((i=1; i<=LIM; i++));do a=`echo $linia | cut -d "," -f$i` #wlasciwe linie z tempa b=`echo $linia1 | cut -d "," -f$i` #linie z bazy c=`echo $linia | cut -d "," -f13` if [ "$host" == "$c" ];then if [ "$a" != "$b" ];then echo ${TAB}":" $b "|" $a fi fi done done < $temp Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
jjj Napisano Luty 28, 2008 Zgłoszenie Share Napisano Luty 28, 2008 Działa długo, bo czas pracy pojedynczego grepa ~ liczba wierszy pliku, razy liczba wierszy daje liczbę wierszy**2. Lepiej czytać pliki sekwencyjnie. Po co się męczyć z shellem? lepiej użyj Perla, do takich zadań jest stworzony. Rozbuduj szkic zgodnie ze swoimi wymaganiami #!/usr/bin/perl open(p1, 'test1.csv'); open(p2, 'test2.csv'); $sep = ","; while ($l1 = <p1>) { $l2 = <p2>; @l1 = split($sep, $l1); @l2 = split($sep, $l2); $n = @l1; for ($i=0; $i<$n; $i++) { print ((@l1[$i] cmp @l2[$i]), $sep); } print "\n"; } close(p2); close(p1); Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Franz Napisano Luty 28, 2008 Autor Zgłoszenie Share Napisano Luty 28, 2008 Fajnie, dzięki. Tyle że mój problem polega na tym, że muszę to napisac w bashu :/.. No ale ewentualnie, pytanie - jak zaimplementować skrypt Perl'a w skrypcie Bash'a ? .. Znaczy, żeby w danej linii został wywołany skrypt Perl i po wykonaniu powrót do bash'a ? Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
jjj Napisano Luty 28, 2008 Zgłoszenie Share Napisano Luty 28, 2008 Cudzych zadań domowych nie robię, a męczyć się z narzędziem niedopasowanym do zadania nie znoszę, zaś doskonalić się w czystym bash-u nie czuję potrzeby. Ale rozumiem, że można mieć inne filozofie i inne uwarunkowania. Skrypt perl-a z prologiem #! jest pełnoprawnym plikiem wykonywalnym; bez prologu wywołasz przez perl nazwa. Wyniki ze stdout odbierzesz przekierowaniem `perl nazwa`. Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
@WalDo Napisano Luty 28, 2008 Zgłoszenie Share Napisano Luty 28, 2008 Cudzych zadań domowych nie robię, Generalnie popieram W ramach nieskomplikowanych pomysłów: może wystarczy użyć diff i przegladać tylko linie różniące się? Odnośnik do komentarza Udostępnij na innych stronach More sharing options...
Rekomendowane odpowiedzi
Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto
Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.
Zarejestruj nowe konto
Załóż nowe konto. To bardzo proste!
Zarejestruj sięZaloguj się
Posiadasz już konto? Zaloguj się poniżej.
Zaloguj się