Bash- porównywanie linii za pomocą tabel

0

Czesc, po kilku komendach otrzymałem plik wyjściowy z którego chcę otrzymać dwie linie które maja ze sobą wspólne kilka kolumn, lecz nie potrafie tego wyciągnąć
oto dwie linie które chce wyciagnac spośród reszty:

NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

maja ze sobą wspólne kilka tabel , różnią sie dwoma.
Jakas propozycja jak je pokazać spośród wszystkich rekordów?
Dzieki

0

Nie wiem czy tego dokładnie chcesz:

$ cat plik
jshdakjshdasd
scasc,sac,asc,asc,asc,
,,,.,dsf,sdf,ds,,,sd,fsd,.
dxksh8n932rn9832x3,f.,3.,34.x,f
xf34,f.34,x.3,4g.3,g.x34,g32/.3zf.,32.f,zx2f
2xg4,.,34.,gx2.3,gx3g,23,,23,4,,3,4,34,xz4,3
,43,f,x,,xf43,x4f,x34,x43///1/23/123/12/3/1%$#%$@^%
%^^%&^@!@\ IJXPD12J	
NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

sakjdhaskhdasdhsak364324NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
329h923yr,2,3,f,23,f,23,xr,3d, NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
d982b3r32xr32xr3rxNAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

$ cat plik | grep -e "NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3"
NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
sakjdhaskhdasdhsak364324NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3

$ cat plik | grep -e "NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3"
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
329h923yr,2,3,f,23,f,23,xr,3d, NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
d982b3r32xr32xr3rxNAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
 
0

ja nie wiem co bedzie po NAZWA1 itp, wiem tylko ,że nazwy są stałem i pośród innych różnią sie zmianami w 1-3 miejscach . Czyli musiałbym jakos wyciągnąć te które najbardziej są do siebie podobne, może coś na zasadzie reguły ,że przynajmniej 4 tabele musza byc takie same zeby można było to wygrepowac?

0

sorry, odpowiedziałem bez zalogowania;)

0

Napisz co jest stałe a co zmienne i pomyślimy o jakimś wyrażeniu regularnym.

0

Witaj,
mam kilkadziesiad lub wiecej takich rekordów, i w tej tabeli niekiedy występuja duplikaty w tabelach, zmienne są różne lecz nie więcej niż w 3 tabelkach.
Lecz zawsze mają minimum 4 tabelki wspólne.
Myślałem wiec o regule która bedzie używała zależności która wyciąga podobne do siebie rekordy spełniające warunek podobieństwa minimum 4 tabelek.

0

Powiedzmy że masz Swoje linijki:

NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

i teraz tak co jest w nich stałe, a co jest zmienne?
Tabela składa się z 10 rekordów oddzielonych przecinkiem.
Musisz podać wzór co chcesz uzyskać i po czym filtrować lub/i podać dodatkowo zależności pomiędzy polami.
Nie ma znaczenia co jest w polach, "bez znaczenia".

Dla przykładu Twoje linijki w dwóch powyższych:
st-stałe; zm - zmienne
st,zm,zm,zm,zm,zm,st,st,st,st

0
hellraiser napisał(a):

Powiedzmy że masz Swoje linijki:

NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

i teraz tak co jest w nich stałe, a co jest zmienne?
Tabela składa się z 10 rekordów oddzielonych przecinkiem.
Musisz podać wzór co chcesz uzyskać i po czym filtrować lub/i podać dodatkowo zależności pomiędzy polami.
Nie ma znaczenia co jest w polach, "bez znaczenia".

Dla przykładu Twoje linijki w dwóch powyższych:
st-stałe; zm - zmienne
st,zm,zm,zm,zm,zm,st,st,st,st

no właśnie tu jest problem, bo ja dostaje dane (linie z tymi rekordami) i nie wiem co sie tam zmieni , musze to porównać.
niekiedy może być tak że w linie bedzie jeden rekord zmieniony na poczatku a niekiedy ,że rokord bedzie zmieniony w środku :
NP:
st,zm,st,st,st,st,st,st,st,st, lub st,st,st,st,st,st,st,st,zm,st musze wspomnieć że każda linia może miec jeden rekord wspólny ale nie zawsze, lecz duble które chce wyświetlić zawsze beda miały przynajmniej 4 lub wiecej wspólnych rekordów.

0

Jak duża jest ta tablica i czy mógłbyś udostępnić kawałek?

0

Czesc, tablica ma różne wymiary i różne zmiany mogą nastąpić podam przykład:

NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3  <Do wyciągnięcia
NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3  <Do wyciągnięcia
NAZWA1, , , ,NAZWA3,N4,NAZWA5,1,1 ,4
NAZWA1, , , ,NAZWA4,N5,NAZWA6,1,1 ,5
NAZWA1, , , ,NAZWA5,N6,NAZWA7,1,1 ,6
NAZWA2, , , ,NAZWA6,N7,NAZWA8,1,1 ,7
NAZWA2, , , ,NAZWA7,N8,NAZWA9,1,1 ,8
NAZWA2, , , ,NAZWA8,N9,NAZWA10,1,1 ,9 
0

Napisałem Ci coś takiego w perlu, może Ci się przyda:

#!/usr/bin/perl

use strict;
use warnings;

################################################################## MAIN
my @main_tab;
my $check_number;
my $type_check;

if(defined($ARGV[0]) and defined($ARGV[1])){
	die "Bad argument \"$ARGV[0]\"" unless($ARGV[0] =~ /^\d+$/);
	die "Bad argument \"$ARGV[1]\"" unless(($ARGV[1] eq 'n') or ($ARGV[1] eq 's') or ($ARGV[1] eq 'ns') or ($ARGV[1] eq 'sn'));
	$check_number = $ARGV[0];
	$type_check = $ARGV[1];
}else{
	die "Bad argument numbers";
}

main_read();
my @returned = create_data();

my @duplicates;
for(my $one_c = 0;$one_c < $#returned+1;$one_c += 2){
	@duplicates = ();
	for(my $two_c = $one_c + 2;$two_c < $#returned+1;$two_c += 2){
		if($type_check eq 'n'){
			push @duplicates,($two_c/2) if($check_number <= compare(\@{$returned[$one_c]},\@{$returned[$two_c]}));
		}elsif($type_check eq 's'){
			push @duplicates,($two_c/2) if($check_number <= compare(\@{$returned[$one_c+1]},\@{$returned[$two_c+1]}));
		}elsif(($type_check eq 'sn') or ($type_check eq 'ns')){
			my $tmp_num = 	compare(\@{$returned[$one_c]},\@{$returned[$two_c]}) + 
					compare(\@{$returned[$one_c+1]},\@{$returned[$two_c+1]});
			push @duplicates,($two_c/2) if($check_number <= $tmp_num);
		}
	}
	if($#duplicates+1 > 0){
		print "Duplicates:\n";
		print "\tline: ".($one_c/2)." \t$main_tab[$one_c/2]\n";
		foreach my $dup(@duplicates){
			print "\tline: ".$dup." \t$main_tab[$dup]\n";
		}
	}
}

###########################################
#
#
# Compare arrays
sub compare{
	my $i = 0;
	(my $first_array,my $second_array, my $type) = @_;
	my @ar_fir = @{$first_array};
	my @ar_sec = @{$second_array};
	for(my $a=0;$a < $#ar_fir+1;++$a){
		last unless($#ar_sec+1);
		for(my $b = 0;$b < $#ar_sec+1;++$b){
			if($ar_fir[$a] eq $ar_sec[$b]){
				++$i;
				splice(@ar_sec,$b,1);
				last;
			}
		}
	}
	return $i;
}

# Read from stdin, string without new line and no nop line
sub main_read{
	while(<stdin>){
		chomp($_);
		push @main_tab,$_ unless($_ =~ /^\s*$/);	
	}
}

# Create structure data
sub create_data{
	my @data = ();
	foreach my $array_element(@main_tab){
		my @numbers = ();
		my @strings = ();
		my @tab = split /,/, $array_element;
		foreach my $var(@tab){
			if($var =~ /^\s*([-]?\d+)\s*$/){
				push @numbers, $1; 
			}elsif($var =~ /^\s*(\S+)\s*$/){
				push @strings, $1;
			}
		}
		@data = (@data,\@numbers,\@strings);
	}
	return @data;
}

Przykładowe użycie to "skrypt ilosc_powtorzen rodzaj(liczby,litery,wspolnie) < plik,lub_strumien"

Przykłady na pliku:

$ ./skrypt.pl 3 s < test.dat 

Duplicates:
	line: 0 	NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3 
	line: 1 	NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
$ ./skrypt.pl 2 s < test.dat 

Duplicates:
	line: 0 	NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3 
	line: 1 	NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
	line: 3 	NAZWA1, , , ,NAZWA4,N5,NAZWA6,1,1 ,5
Duplicates:
	line: 1 	NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3
	line: 3 	NAZWA1, , , ,NAZWA4,N5,NAZWA6,1,1 ,5
Duplicates:
	line: 2 	NAZWA1, , , ,NAZWA3,N4,NAZWA5,1,1 ,4
	line: 4 	NAZWA1, , , ,NAZWA5,N6,NAZWA7,1,1 ,6
Duplicates:
	line: 5 	NAZWA2, , , ,NAZWA6,N7,NAZWA8,1,1 ,7
	line: 7 	NAZWA2, , , ,NAZWA8,N9,NAZWA10,1,1 ,9

$ ./skrypt.pl 3 n < test.dat 
Duplicates:
	line: 0 	NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3 
	line: 1 	NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

$ ./skrypt.pl 7 ns < test.dat 
Duplicates:
	line: 0 	NAZWA1, , , ,NAZWA2,N3,NAZWA4,1,1 ,3 
	line: 1 	NAZWA1, , , ,N3,NAZWA2,NAZWA4,1,1 ,3

Jak będziesz potrzebował to dopiszę kilka komentarzy.

0

Czesc, dzieki za propozycje, na prawde ciekawe. mam jeszcze pytania do Ciebie.
przy mieleniu w każdej lini musze tworzyc pliki tymczasowe żeby w kolejnej linii brac kolejno przetworzone dane.
1.Czy jest możliwość stworzenia jakiegoś hiperłącza które by brało lokalizacje folderu tam gdzie aktualnie znajduje sie skrypt?
2. Wiesz może jak odpalić skrypt .sh bez przeciągania go do terminala? np poprzez podwójne kliknięcie?
Dzieki

0

Na debianie korzystam z polecenia mimeopen.
$ mimeopen skrypt.sh
<Tutaj wybieram program np /bin/bash>

Po tej operacji klikanie skryptu powoduje jego uruchomienie za pomocą bash'a. Nie jest potrzebne prawo do wykonywania "x".

0
hellraiser napisał(a):

Na debianie korzystam z polecenia mimeopen.
$ mimeopen skrypt.sh
<Tutaj wybieram program np /bin/bash>

Po tej operacji klikanie skryptu powoduje jego uruchomienie za pomocą bash'a. Nie jest potrzebne prawo do wykonywania "x".

to bedzie na windowsie leciec, mam to do mojego skryptu wrzucic na start i od tego zaczac linie?

0

Opisz dokładnie co chcesz uzyskać i z czego korzystasz, bo będziemy postowali w nieskończoność.
Jakie pliki, co wykorzystujesz, jak chcesz porównywać lub co wyciągać.
Z jakiej platformy korzystasz, w jaki sposób działasz, jak chcesz to uruchamiać i na czym.
I pewnie jeszcze wiele innych. Opisz wszystko w szczegółach, to pozwoli mi coś Tobie doradzić.

0

juz wszystko ogarnąłem , wszystkie pliki na których pracuje juz sa pod kontrolą . skrypt jest gotowy.

Co chce jeszcze uzyskac, jeżeli jest możliwość to uruchamianie skryptu za pomoca klikniecia ( na razie uruchamiam go przeciągając do cygwina, czyli ustalajac jego sciezke i enter)
Wszystko leci na windows 7 64 bit.

Jedyny problem prócz tego uruchamiania jaki napotkałem na końcu to komunikat przy wrzuceniu duzego pliku , ktory wyskakuje mi w cygwinie:
grep: memory exhausted przeczytałem ,ze jakos mozna powiekszysc pamiec ktora wykorzystuje cygwin ale nie wiem jeszcze jak wiec jak ktos miał podobny problem i go rozwiazał to bede wdzieczny za pomoc.
Pozdrawaim

0

mały update: stworzyłem blik bat za pomoca ktorego odpalam skrypt.
co do problemu z pamiecia, podczas odpalania skryptu sprawdziłem i wykorzystuje max pamieci kompa i procesora. Czy ktoś wie co z tym zrobić może to przez sama komende grep on sie wywala? nie mam pojacia dlaczego tak bardzo pamiec obciąża.

0
yoseph napisał(a):
hellraiser napisał(a):

Na debianie korzystam z polecenia mimeopen.
$ mimeopen skrypt.sh
<Tutaj wybieram program np /bin/bash>

Po tej operacji klikanie skryptu powoduje jego uruchomienie za pomocą bash'a. Nie jest potrzebne prawo do wykonywania "x".

to bedzie na windowsie leciec, mam to do mojego skryptu wrzucic na start i od tego zaczac linie?

temat ogarnąłem , -F dodałem i bangla.
kolejny problem , czy ktoś mi powie dlaczego nie działa mi reguła :
jeżeli jeden wskazany plik jest pusty, to usun drugi plik wskazany
if -s plik1
then
rm -f plik 2

??

1 użytkowników online, w tym zalogowanych: 0, gości: 1