16. 6. 2016 - expdbf

Seznámení se základními principy operačního systému UNIX, převážně z uživatelského hlediska. Absolvent kurzu by měl být schopen napsat netriviální program v shellu.
r.zikmund
Matfyz(ák|ačka) level I
Příspěvky: 2
Registrován: 16. 6. 2016 19:49
Typ studia: Informatika Bc.

16. 6. 2016 - expdbf

Příspěvek od r.zikmund »

Dnes se opakovalo zadání expdbf (http://forum.matfyz.info/viewtopic.php? ... dbf#p16148)

Oproti verzi výše jen drobné změny, ale pro jistotu napíšu vše co si pamatuji:

Ze začátku sáhodlouze vysvětloval jak vůbec formát dbf vypadá, ve zkratce se jedná o binární formát vypadající následovně:
Hlavička - 32 B - ta nás nezajímala, měli jsme ji rovnou přeskočit

pak následuje popis sloupců vždy v 32B blocích/sloupec:
1.-11. - B obsahují jednoznačný identifikátor sloupce (alfanum. znaky, bez mezer atd.), případný kratší název je zprava doplněn mezerami na 11 znaků.
17. B - binárně uložená šířka sloupce
zbytek v bloku jsou data, která jsou pro nás nezajímavá

popis sloupců je ukončen znakem CR (binárně 13), a hned následujícím bytem začínají záznamy fixní délky (součet délek sloupců), ve kterých jsou za sebou uložené textové reprezentace jednotlivých sloupců, opět případně zprava doplněné mezerami na danou délku.

Celý soubor je pak zakončen znakem 0x1A (mám pocit že je to backspace, ale to je nedůležitý)

Samotné zadání:
Vytvořte skript, kterému jako parametry předáme nejprve názvy sloupců a poté názvy databázových souborů a vypíše odpovídající sloupce v uživatelem zadaném pořadím (odděleném tabulátorem).

z diskuze vyplynulo:
- bylo nám důrazně doporučeno řešení rozdělit vhodně do funkcí
- Je zakázáno číst soubor O(n) krát. Jedná se o čtení, nikoliv otevření, byly nám doporučeny 2 přístupy, buď pomocí splitu rozdělit (s použitím posixové verze, tedy rozdělí na max. 26^2 souborů, takže je třeba chytře použív víckrát), nebo pomocí příkazů, které umí seekovat (tedy kombinace head a tail s přepínačem -c)
- Databázový soubor může být velký, takže se nevejde do paměti.
- Správnost vstupu, tedy žádané sloupce v databázi jsou. Také máme jistotu, že jméno sloupce není shodné se jménem žádného souboru v adresáři (tedy pomocí testu na existenci souboru lze určit, kdy končí seznam sloupců a začíná seznam souborů).
- Dále nám dovolil předpokládat, že všechny soubory mají stejné sloupce ve stejném pořadí (což pro řešení téměř nepomůže) a navíc mají koncovku .dbf (též se to dalo udělat jednoduše i bez této znalosti)
- Názvy sloupců jsou case-insensitive
- V obsahu sloupců se nevyskytují znaky \t a

- Všechny mezery uvnitř hodnot musíme zachovat, naopak ty vpravo musíme odříznout

k řešení byl doporučen i příkaz

Kód: Vybrat vše

od -t u1 soubor
ten vypíše jednotlivé byty souboru v číselné podobě (v desítkové), přičemž vypisuje 32B na řádek (později jsem od někoho slyšel že vypisuje jen 16, ale měli jsme počítat se 32), což se nám poměrně dost hodí na získání délek sloupců (ale nedoporučoval jej použít pro získání názvů sloupců, tj s následnou konverzí číslo -> znak).

Zadání + diskuze trvalo asi hodinu, mnoha lidem dělalo problém pochopit formát (pro ty co ho ode mě nepochopili, v Shell v příkladech na str. 208 je vysvětlen i s obrázkem, navíc ti co tu knížku měli s sebou mohli podstatnou část řešení úlohy odtud opsat, protože ten příklad vypadal velmi podobně, avšak nevím jak se na to pak Forst při opravování tvářil)

Forstovy poznámky k řešení:
získání formátu databáze - pomocí od čtu řádky, dokud na offsetu dělitelném 32 není 13 (to jest, neskončil popis sloupců), z tohoto jsme měli zjistit kolik je a jaké jsou jejich délky, názvy pak získat ve zvláštním cyklu pomocí

Kód: Vybrat vše

tail -c+${offset} 1 | head -c11
dalo se to dělat i opačně (nejdřív získat názvy, pak délky), nicméně pak bylo vhodné si nějak získat offsety toho, co uživatel chce vypsat. Hodně nadával, když to někdo matchoval při každém výpisu, měli jsme si připřavit někam offsety a délky už v pořadí, jakém jsme to měli vypisovat

samotné vypisování, jak už nastínil při zadání, se dalo řešit 2 způsoby:
1) počítáním potřebných offsetů v souboru a furt je přepočítávat, což je podle Forsta děsnej opruz, nicméně tento způsob jsme zvolili všichni až na 1
2) použití splitu, kdy jsme nejdřív museli získat délku jednoho záznamu a pak chytře v cyklu rozkládat, dokud nemáme každý záznam v jednom souboru

Největší chyby:
Dalo by se to asi i velmi hezky řešit pomocí evalu, nicméně asi není uplně jednoduchý odladit quoting, což pak hodně lidem vytýkal
dále se mu velmi nelíbilo když někdo celý octal dump souboru uložil na disk (tedy z 2GB souboru vytvořil více než 6GB kopii, ze které přečetl prvních pár bytů)
Další kámen úrazu bylo nastavování proměnných za rourou, spousta lidí si pečlivě nastavilo hromadu proměnných, a po ukončení subshellu o ně přišla

Výsledek (nepamatuji si přesně):
4x1
1x2 (vážně si myslím že byla jenom 1)
5x ústní
zbytek do 17 vyházel, tedy úspěšnost poměrně malá, v tomhle zkouškovém už se úloha na binární data prej neobjeví, protože má asi jenom tuhle.
Odpovědět

Zpět na „SWI095 Úvod do UNIXu“