Skocz do zawartości

Porównanie Linii Sed Vs. Awk


Franz

Rekomendowane odpowiedzi

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

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

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

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

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ę
×
×
  • Dodaj nową pozycję...