Portál AbcLinuxu, 24. dubna 2024 17:33


Dotaz: porovnani 2 souboru bash

22.12.2012 17:54 mofas
porovnani 2 souboru bash
Přečteno: 636×
Odpovědět | Admin
Zdravim, darky zabaleny a tak si hraju s bashem, protoze potrebuju jednu takovou vecicku udelat. Mam 2 soubory, ktere oba obsahuji vzdy jen jeden rezetec na jednom radku. Tech retezcu je pod sebou i nekolik tisic. Nekdy se tyto retezce shoduji. A ja jsem si udelal program, ktery veme radek z kazdeho souboru, porovna je a vypise mi pouze ty retezce, ktere se nenachazeji v to prvnim souboru. Jak uz jsem rekl, mam to napsane, ale funguje to polovicate a nechapu proc (uz jsem aj buchnul do stolu a nic).

Muj kod:

while read radek; do

if [ "`grep -i $radek $2`" != "`grep -i $radek $1`" ]; then
      echo $radek >> vysledek.txt
else
      echo $radek >> /dev/null
fi

done < $1

Program spoustim takhle:

./ program.sh soubor_1 soubor_2

Uvedu priklad:

soubor_1 obsahuje:

a

b

c

d

e

f

g

soubor_2 obsahuje:

g

b

e

d

i

g

vysledny soubor vysledek.txt obsahuje:

a

c

f

g

Je to spravne, jen ten posledni znak g tam nema byt, proc tam je? Vzdyt se nachazi v obou souborech. Tohle mi hlava nebere

Podotykam, že $1 je soubor_1 a $2 je soubor_2. Diky za nakopnuti a preju hezke svatky!

Řešení dotazu:


Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

pepe_ avatar 22.12.2012 18:15 pepe_ | skóre: 48
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Odpovědět | | Sbalit | Link | Blokovat | Admin

A co konec řádku , není tam cr_lf nebo nějakej podobnej paznak kterej neni vidět ?

22.12.2012 18:36 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
pod posledním řetězcem v obou souborech je pouze prázdný řádek. Jinak vždy na každém řádku vedle řetězce není nikdy žádný bílý znak nebo cokoliv neviditelného.
22.12.2012 18:26 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Odpovědět | | Sbalit | Link | Blokovat | Admin
To musí být hrozně pomalé. Nebyl by lepší diff?

Potřebuješ to k nějaké funkčnosti nebo je to jen cvičení?
22.12.2012 18:42 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Ještě před dvěma hodina jsem měl řešení s diffem, ale asi jsem ho špatně pochopil, protože mi vypisoval i řádky, které se shodují v obou souborech. Však diff prochází tak, že veme první řádek z prvního souboru a první řádek z druhého souboru a porovná je...pak zase veme druhé řádky z obou souborů atd.. Jenže když se řádky, které se shodují, budou každý jinde v souboru, tak to už neodhalí, nebo se mýlím?

Pomalé to je, a ještě se to zpomalilo, když jsem tam dodal do podmínky tohle:

if [ "`grep -i $radek $2 | tr [A-Z] [a-z]`" != "`grep -i $radek $1 | tr [A-Z] [a-z]`" ]; then

Zkrátka, aby to převedlo všechno na malé znaky...aby mi to nevyhodilo neshodu na základě toho, že se někde v řetězci nachází velké písmenko.
22.12.2012 19:06 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Pokud nezáleží na pořadí, je možné záznamy před diff seřadit sortem.

Také je možné první soubor natáhnout do nějakého asociativního pole a druhý soubor s ním porovnat.
22.12.2012 19:17 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Jeejda, na sort jsem uplně zapomněl. Díky. To asociativní pole, s tím vůbec zkušenosti nemám, nevím jak by se to dělalo. Ono až tak nezáleží jak rychle to pojede. Ted jsem si zkusil 2 největsi soubory a za minutku to bylo hotove.

Ze zvědavosti, mohl byste nastánit jak by to s tím asoc. polem vypadalo? Celkem mě to zajímá. Díky
22.12.2012 19:37 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Nejlepší by to asi bylo v Perlu, ale zrovna mě napadlo to vyzkoušet v SQLite:
#!/bin/bash

sqlite3 <<EOT
.separator '|||'
create table a(nazev text);
.import a.txt a
create index inda on a (nazev);
create table b(nazev text);
.import b.txt b
select nazev from b where lower(nazev) not in (select lower(nazev) from a);
EOT
22.12.2012 20:06 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
co jsem tam koukal, tak i bash ma nejake pole. Diky za nastin reseni!
22.12.2012 20:20 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
To je sice pravda, ale snad každý jazyk to má vyřešeno lépe. Třeba v PHP to také není těžké:
<?php
$a=array();
foreach (file('a.txt') as $line) {
    $a[strtolower(trim($line))]=$line;
}
foreach (file('b.txt') as $line) {
    if (!isset($a[strtolower(trim($line))])) {
        echo trim($line),"\n";
    }
}
22.12.2012 20:54 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
skvělé, tak tohle je i na první pohled čitelnější a jistě rychlejší ;) Díky ještě jednou
24.12.2012 04:44 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
…ale jen dokud se vejdete do paměti.
24.12.2012 07:20 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Těch řádek je dle dotazu jen několik tisíc. Předpokládám, že jsou "normálně" dlouhé a že problém s RAM nebude muset řešit. Jinak může použít DB.
24.12.2012 03:56 deadmail
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Odpovědět | | Sbalit | Link | Blokovat | Admin
Rozdiely (co je len v prvom, len v druhom alebo v obochoch) dvoch usporiadanych suborov vypisuje comm.

Len v druhom:
comm -13 <(sort soubor_1) <(sort soubor_2)
24.12.2012 14:54 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
děkuju, o tomto příkazu jsem snad ještě neslyšel! Nicméně řešení je rychlé a efektivní. Díky
24.12.2012 14:59 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Tedy až na to, že mi to vypíše znova skoro celý soubor. Při parametru pouze "-3" to ve vyslednem souboru sice ukáže znova všechno, ale řádky, které se liší, tak ty nechá na začátku řádky a před všechny zbylé řádky hodí tabulátor.
24.12.2012 17:34 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
i kdyz to spustim jen s parametrem "-3" tak mi to vypíše jako neshodu 2 shodne retezce.

Jak může comm říct, že tohle jsou rozdílné řetězce:

Robert_Natus_-_Back_To_Led_(Holz56)-Promo_EP-2002-TR

Robert_Natus_-_Back_To_Led_(Holz56)-Promo_EP-2002-TR

??? Žádný rozdíl ve velikosti znaku, žádné bílé znaky, žádné jiné neviditelné znaky....
24.12.2012 18:15 Kit
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Když si to vypíšeš hexdumpem, možná nějaký rozdíl najdeš.
24.12.2012 20:52 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
tak už jsem to rozchodil. Nevím doted jaká byla přesná chyba, ale když už jsem z toho pomalu šílel a naprosto totožný kod dělal něco jiného než předtím, tak jsem resetoval system, a pak už bylo vše v pořádku. comm je skvělý nástroj, trošku jsem si to upravil, aby neuvažoval rozdíl ve velikosti písmen:

comm -3 <(cat $1 | tr [A-Z] [a-z] | sort) <(cat $2 | tr [A-Z] [a-z] | sort) > vysledek.txt

Díky ještě jednou!
24.12.2012 04:41 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Odpovědět | | Sbalit | Link | Blokovat | Admin

1. V jednom souboru máte řádek "g" jednou a ve druhém dvakrát, proto vám to porovnání nevyjde.

2. Kromě zoufalé neefektivity je použití grepu špatně, protože grep vám vrátí i všechny řádky, kde se vzorek vyskytuje jako podřetězec. Co hůř, vzorek se chápe jako (basic) regulární výraz, takže bude-li obsahovat např. tečku, nebudete se stačit divit, co všechno bude matchovat.

3. K čemu je podle vás dobrá ta "else" větev (kromě zpomalení skriptu)?

24.12.2012 15:06 mofas
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
ad 1. chápu

ad 2. chápu, je to pomalé a neefektivní (zplácal jsem to za pár minut), nicméně funguje jak má (ještě jsem to trochu dovylepšil). Abych grepu zabránil brát vzorec jako basic RE, tak stačí dát vzorek do uvozovek "$vzorek"?

ad 3. moje blbost, stydím se, díky za upozornění!
24.12.2012 21:52 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: porovnani 2 souboru bash
Abych grepu zabránil brát vzorec jako basic RE, tak stačí dát vzorek do uvozovek "$vzorek"?

Ne, tím jen zařídíte, aby shell neinterpretoval znaky, které jsou pro něj speciální (třeba mezery). Pro chápání vzorku jako řetězce by měl pomoci přepínač -F (nebo spouštět jako fgrep). Ale pořád bude potřeba dávat pozor na podřetězce nebo vícenásobné výskyty (podle způsobu použití).

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.