Prosíme přihlašte se nebo zaregistrujte.

Přihlašte se svým uživatelským jménem a heslem.
Vaše pomoc je stále potřeba!

Autor Téma: Optimalizace skriptu  (Přečteno 2595 krát)

Václav Sobota

  • Aktivní člen
  • *
  • Příspěvků: 222
Optimalizace skriptu
« kdy: 17 Listopadu 2013, 22:42:33 »
V tematu Pomoc se skriptem v sedu jsem resil import a upravu dat z internetoveho zdroje. Vysledek vsak nebyl zcela uspokojivy.

Ten skript jsem tedy kompletne prekopal - presel jsem na Yahoo Finance, kteri kurzovni data normalne poskytuji (puvodne jsem ale nevedel, ze maji primo takovy "data feed" a skutecne vsechny meny). Ale nevyhoda je, ze jednotlive, ne davkove. Takze pro 20 men je to stazeni 20ti souboru wgetem, coz je docela pomale. To by ani tolik nevadilo (me ta pomalost vadila pri primem html importu do LibreOffice Calcu, protoze Calc je behem stahovani dat zasekly, ale nezobrazuje se prubeh a tak neni znat, ze/zda neco dela).

Dospel jsem tedy k nasledujicimu reseni:

1) Mam "ridici skript":
Kód: [Vybrat]
#!/bin/bash

# Skript, ktery vyvola stazeni aktualnich kurzu z internetu a jejich import do tabulky

folder=".YahooFinance"
subfolder="TemporaryData"
soubor="Yahoo.csv"
datum=`date +'%Y-%m-%d'`
path="/home/`whoami`/Dokumenty"
tabulka="Portfolio manager.ods"

mate-terminal -x "/home/`whoami`/"$folder"/SkriptYahoo"
# Spusti v terminalu uvedeny skript, terminal se potom zavre

libreoffice --calc "$path"/"$tabulka"
# v LibreOffice Calcu spusti pozadovanou tabulku

exit 0
Ten jsem vytvoril proto, aby se skript "SkriptYahoo" viditelne spustil v terminalu a tim dal uzivateli najevo, ze se neco deje a je treba chvilku pockat.

Samotny skript "SkriptYahoo" je nasledujiciho zneni:
Kód: [Vybrat]
#!/bin/bash

folder=".YahooFinance"
subfolder="TemporaryData"
soubor="Yahoo.csv"
datum=`date +'%Y-%m-%d'`

if [ -d /home/`whoami`/"$folder" ]
  then echo "Folder $folder already exists"
  else cd /home/`whoami`/ ; mkdir "$folder"; cd "$folder"/
fi
# Pokud slozka program juste neexistuje, je vytvorena

if [ -f /home/`whoami`/"$folder"/"$soubor" ]
  then rm /home/`whoami`/"$folder"/"$soubor"
  else echo "A new $soubor file will be created"
fi
# Pokud jiz existuje soubor s daty, je smazan

if [ -d /home/`whoami`/"$folder"/"$subfolder" ]
  then echo "Folder $subfolder already exists"
  else cd /home/`whoami`/"$folder"/ ; mkdir "$subfolder" ; cd "$subfolder"/
fi
# Pokud jeste neexistuje slozka na docasna data, je vytvorena

cd /home/`whoami`/"$folder"/"$subfolder"/

echo "Starting data download..."

wget -O 'AMD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKAMD=X'
wget -O 'AUD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKAUD=X'
wget -O 'AZN.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKAZN=X'
wget -O 'BGN.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKBGN=X'
wget -O 'CAD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKCAD=X'
wget -O 'CHF.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKCHF=X'
wget -O 'CLP.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKCLP=X'
wget -O 'CZK.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKCZK=X'
wget -O 'EUR.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKEUR=X'
wget -O 'GBP.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKGBP=X'
wget -O 'GEL.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKGEL=X'
wget -O 'HKD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKHKD=X'
wget -O 'HUF.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKHUF=X'
wget -O 'KGS.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKKGS=X'
wget -O 'KRW.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKKRW=X'
wget -O 'KZT.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKKZT=X'
wget -O 'LTL.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKLTL=X'
wget -O 'LVL.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKLVL=X'
wget -O 'MDL.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKMDL=X'
wget -O 'MKD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKMKD=X'
wget -O 'MNT.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKMNT=X'
wget -O 'MYR.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKMYR=X'
wget -O 'NZD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKNZD=X'
wget -O 'PHP.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKPHP=X'
wget -O 'PLN.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKPLN=X'
wget -O 'PYG.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKPYG=X'
wget -O 'RON.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKRON=X'
wget -O 'RSD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKRSD=X'
wget -O 'RUB.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKRUB=X'
wget -O 'SGD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKSGD=X'
wget -O 'THB.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKTHB=X'
wget -O 'TJS.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKTJS=X'
wget -O 'TMT.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKTMT=X'
wget -O 'TRY.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKTRY=X'
wget -O 'UAH.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKUAH=X'
wget -O 'USD.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKUSD=X'
wget -O 'UZS.csv' 'http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZKUZS=X'

touch "$soubor"

cat AMD.csv >> $soubor
cat AUD.csv >> $soubor
cat AZN.csv >> $soubor
cat BGN.csv >> $soubor
cat CAD.csv >> $soubor
cat CHF.csv >> $soubor
cat CLP.csv >> $soubor
cat CZK.csv >> $soubor
cat EUR.csv >> $soubor
cat GBP.csv >> $soubor
cat GEL.csv >> $soubor
cat HKD.csv >> $soubor
cat HUF.csv >> $soubor
cat KGS.csv >> $soubor
cat KRW.csv >> $soubor
cat KZT.csv >> $soubor
cat LTL.csv >> $soubor
cat LVL.csv >> $soubor
cat MDL.csv >> $soubor
cat MKD.csv >> $soubor
cat MNT.csv >> $soubor
cat MYR.csv >> $soubor
cat NZD.csv >> $soubor
cat PHP.csv >> $soubor
cat PLN.csv >> $soubor
cat PYG.csv >> $soubor
cat RON.csv >> $soubor
cat RSD.csv >> $soubor
cat RUB.csv >> $soubor
cat SGD.csv >> $soubor
cat THB.csv >> $soubor
cat TJS.csv >> $soubor
cat TMT.csv >> $soubor
cat TRY.csv >> $soubor
cat UAH.csv >> $soubor
cat USD.csv >> $soubor
cat UZS.csv >> $soubor

mv /home/`whoami`/"$folder"/"$subfolder"/"$soubor" /home/`whoami`/"$folder"/

rm -rf /home/`whoami`/"$folder"/"$subfolder"

echo "Data successfully downloaded"

echo "Program will close in 3 seconds..."

sleep 2s

exit 0

Ten wget by se dal asi zrychlit presunutim nekterych uloh na pozadi (&), ale mohlo by to mit podle me za nasledek, ze ta tabulka se otevre driv, nez vubec bude vsechno stazeno, nebo zapis a smazani podslozky by mohlo probehnou predcasne.

Je evidentni, ze prinejmensim ta serie cat by se dala nahradit necim jako
Kód: [Vybrat]
#!/bin/bash

folder=".YahooFinance"
subfolder="TemporaryData"
soubor="Yahoo.csv"

for i in *.csv; do
    [ -e "$i" ] || continue
    cat $i >> $soubor
done

Ale ma to par uskali, kvuli kterym jsem to zatim neaplikoval (razeni men v tabulce vs. abecedni razeni catem - soubor z Yahoo Finance neobsahuje symbol meny, pouze kurz).

Hlavnim nametem k optimalizaci by tedy bylo:

1) Aby vsechny ulohy wgetu probehly soucasne, ale skript nepokracoval dokud neprobehnou vsechny, NEBO aby se stahovali postupne, ale stazene soubory se zapsali jeden po druhem do jedinneho souboru (je jedno jestli do rady s nejakym oddelovacem, nebo nova hodnota na kazdy radek).

2) Integrovat do odkazu pro wget jakousi "variabilni promennou", cimz myslim to, ze ten symbol druhe meny by se bral postupne z nejakeho seznamu (v jinem souboru), dokud by se nedoslo na konec.

3) Integrovat kod meny do stazeneho souboru (napr. pro CZKCLP se stahne soubor o obsahu 0.25 a treba sedem bych na zacatek radky vlozil CLP;.

Prinejmensim tu 3) bych asi zvladl sam, nicmene by to asi nebyl zrovna ortodoxni skript... Predem dekuji za vsechny rady, navody a pripominky! :)

Jinak jedna zvlastnost - pokud dam skript PortfolioManager "spustit", vse probehne naprosto v poradku. Pokud ale zvolim "Spustit v terminalu", nepocka se na ukonceni SkriptYahoo a okamzite se spousti i LibreOffice. V zasade mi to nevadi (spoustet v terminalu se nema), ale prekvapuje me to...
« Poslední změna: 17 Listopadu 2013, 23:42:49 od Václav Sobota »

GdH

  • Moderátor
  • Závislák
  • ***
  • Příspěvků: 3176
    • GdH-Notes
Re:Optimalizace skriptu
« Odpověď #1 kdy: 18 Listopadu 2013, 00:01:37 »
A co třeba takto:
Kód: [Vybrat]
#!/bin/bash

folder="$HOME/.YahooFinance"
file="$folder/Yahoo.csv"

mkdir -p "$folder"
rm -f "$file"

echo "Starting data download..."
cur="AMD\nAUD\nAZN\nBGN\nCAD\nCHF\nCLP\nCZK\nEUR\nGBP\nGEL\nHKD\nHUF\n\
KGS\nKRW\nKZT\nLTL\nLVL\nMDL\nMKD\nMNT\nMYR\nNZD\nPHP\nPLN\nPYG\nRON\n\
RSD\nRUB\nSGD\nTHB\nTJS\nTMT\nTRY\nUAH\nUSD\nUZS"
echo -e $cur | while read c
   do wget -O - "http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZK$c=X" >> $file
done
echo "Data successfully downloaded"
exit 0

Paralelizovat v tomto případě stahování mi přijde jako zbytečná komplikace a poslat si na začátek každé řádky kód měny je trivialita.

A pak mě napadá, jestli by ti nestačil výstup ČNB..
« Poslední změna: 18 Listopadu 2013, 00:12:20 od GdH »

Václav Sobota

  • Aktivní člen
  • *
  • Příspěvků: 222
Re:Optimalizace skriptu
« Odpověď #2 kdy: 18 Listopadu 2013, 00:20:58 »
A co třeba takto:
Kód: [Vybrat]
#!/bin/bash

folder="$HOME/.YahooFinance"
file="$folder/Yahoo.csv"

mkdir -p "$folder"
rm -f "$file"

echo "Starting data download..."
cur="AMD\nAUD\nAZN\nBGN\nCAD\nCHF\nCLP\nCZK\nEUR\nGBP\nGEL\nHKD\nHUF\n\
KGS\nKRW\nKZT\nLTL\nLVL\nMDL\nMKD\nMNT\nMYR\nNZD\nPHP\nPLN\nPYG\nRON\n\
RSD\nRUB\nSGD\nTHB\nTJS\nTMT\nTRY\nUAH\nUSD\nUZS"
echo -e $cur | while read c
   do wget -O - "http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZK$c=X" >> $file
done
echo "Data successfully downloaded"
exit 0

Paralelizovat v tomto případě stahování mi přijde jako zbytečná komplikace.

To je to co jsem mel zhruba na mysli :) Brzo to vyzkousim... Fungovalo by dat tu promenou cur do externiho souboru, napr.
Kód: [Vybrat]
cur=`cat Soubor_s_promennymi.txt`?
Samozrejme si nejsem uplne jisty, jestli by to k necemu bylo, protoze by se musel dodrzet (predpokladam) te format zapisu. Mohl bych taky udelat CSVckovou tabulku s menami a nechat ji do promene nacist sedem, ktery by vsechny radky pospojoval a oddelovace nahradil \n. To by predpokladam bylo zhruba
Kód: [Vybrat]
sed -e :a -e '$!N;s/\n;/;/;ta' -e 'P;D' ; sed -e 's/;/\/n/g' (Nejsem si tim uplne jistej, ted to nemohu vyzkouset). Tenhle "link" by mohl vest primo do te uzivatelske tabulky... Ale nevim, jestli to nebude uz prilis komplikaci...?

Václav Sobota

  • Aktivní člen
  • *
  • Příspěvků: 222
Re:Optimalizace skriptu
« Odpověď #3 kdy: 18 Listopadu 2013, 15:41:58 »

Paralelizovat v tomto případě stahování mi přijde jako zbytečná komplikace a poslat si na začátek každé řádky kód měny je trivialita.

A pak mě napadá, jestli by ti nestačil výstup ČNB..

Tak CNB byl uplne prvni zdroj, ktery jsem zkousel. Maji ale zoufale malo men. Ja se pohybuji hlavne v menach byvaleho SSSR + ty standardnejsi (AUD, SGD, USD, CAD EUR, GBP...) a neco malo z Jizni Ameriky. CNB prave nabizi jenom ty standardni meny...

Václav Sobota

  • Aktivní člen
  • *
  • Příspěvků: 222
Re:Optimalizace skriptu
« Odpověď #4 kdy: 18 Listopadu 2013, 16:34:07 »
A co třeba takto:
Kód: [Vybrat]
#!/bin/bash

folder="$HOME/.YahooFinance"
file="$folder/Yahoo.csv"

mkdir -p "$folder"
rm -f "$file"

echo "Starting data download..."
cur="AMD\nAUD\nAZN\nBGN\nCAD\nCHF\nCLP\nCZK\nEUR\nGBP\nGEL\nHKD\nHUF\n\
KGS\nKRW\nKZT\nLTL\nLVL\nMDL\nMKD\nMNT\nMYR\nNZD\nPHP\nPLN\nPYG\nRON\n\
RSD\nRUB\nSGD\nTHB\nTJS\nTMT\nTRY\nUAH\nUSD\nUZS"
echo -e $cur | while read c
   do wget -O - "http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZK$c=X" >> $file
done
echo "Data successfully downloaded"
exit 0

Paralelizovat v tomto případě stahování mi přijde jako zbytečná komplikace a poslat si na začátek každé řádky kód měny je trivialita.

A pak mě napadá, jestli by ti nestačil výstup ČNB..

Tak jsem po tvem vzoru zmenil ten kod na:
Kód: [Vybrat]
#!/bin/bash

folder="/home/`whoami`/.YahooFinance"
file="$folder/Yahoo.csv"
datum=`date +'%Y-%m-%d'`

mkdir -p "$folder"
# vytvori slozku $folder pokud neexistuje. pokud ano, nebude hlasit chybu (diky -p )

rm -f "$file"
# -f zpusobi, ze pokud soubor $file neexistuje, prikaz bude ignorovan. nebude vyzadovat potvrzeni smazani

echo "Starting data download..."

cur="AMD\nAUD\nAZN\nBGN\nCAD\nCHF\nCLP\nCZK\nEUR\nGBP\nGEL\nHKD\nHUF\n\
KGS\nKRW\nKZT\nLTL\nLVL\nMDL\nMKD\nMNT\nMYR\nNZD\nPHP\nPLN\nPYG\nRON\n\
RSD\nRUB\nSGD\nTHB\nTJS\nTMT\nTRY\nUAH\nUSD\nUZS"
# "Variabilni promenna" - bude postupne vracet hodnoty oddelene \n od prvni do posledni

echo -e $cur | while read c
# prikaz echo zacne postupne cist promenou $cur, zatimco while read bude hodnotu reportovanou echem zapisovat do wgetu
   do wget -O - "http://finance.yahoo.com/d/quotes.csv?f=l1&s=CZK$c=X" >> $file
done

echo "Data successfully downloaded"

exit 0

Musim rict, ze to (samozrejme) funguje bezvadne. Pridal jsem si tam par komentaru, doufam z jsem vsechno pochopil spravne. Akorat mi funkce toho " | " pripada spis jako AND nez OR, a nebo to uz mam nejak pomotany ;D

Jedne veci ale moc nerozumim - mam promennou cur, ale read a posleze i wget pracuje s c. Neni mi jasne, jakym zpusobem se c definovalo?

GdH

  • Moderátor
  • Závislák
  • ***
  • Příspěvků: 3176
    • GdH-Notes
Re:Optimalizace skriptu
« Odpověď #5 kdy: 18 Listopadu 2013, 16:58:01 »
V shellu je | tzv. roura, nikoliv OR (ten se píše zdvojeně || ). echo nečte nic postupně, ale prostě to narve do roury najednou. Za rourou je smyčka while/do/done, která provádí příkazy mezi do a done, dokud má read (jehož návratová hodnota je podmínkou cyklu) co z roury číst. A read v každém průběhu přečte řádek z roury, uloží ho do $c, kterou pak shell expanduje v linku pro wget a ten stáhne patřičný soubor. Ty znaky \n v $cur reprezentují konce řádků a přepínač -e u echa způsobí, že budou jako takové interpretovány. Když si to rozložíš do souboru po řádcích, tak je tam samozřejmě potřebovat nebudeš.

Jinak jsem roury a přesměrování obecně podrobně rozebral tady:
http://gdhnotes.blogspot.cz/2013/05/presmerovani-roury-bash.html

EDIT: trochu jsem rozepsal tu smyčku, když je konečně čas :)
« Poslední změna: 18 Listopadu 2013, 19:50:52 od GdH »

Václav Sobota

  • Aktivní člen
  • *
  • Příspěvků: 222
Re:Optimalizace skriptu
« Odpověď #6 kdy: 18 Listopadu 2013, 21:23:08 »
V shellu je | tzv. roura, nikoliv OR (ten se píše zdvojeně || ). echo nečte nic postupně, ale prostě to narve do roury najednou. Za rourou je smyčka while/do/done, která provádí příkazy mezi do a done, dokud má read (jehož návratová hodnota je podmínkou cyklu) co z roury číst. A read v každém průběhu přečte řádek z roury, uloží ho do $c, kterou pak shell expanduje v linku pro wget a ten stáhne patřičný soubor. Ty znaky \n v $cur reprezentují konce řádků a přepínač -e u echa způsobí, že budou jako takové interpretovány. Když si to rozložíš do souboru po řádcích, tak je tam samozřejmě potřebovat nebudeš.

Jinak jsem roury a přesměrování obecně podrobně rozebral tady:
http://gdhnotes.blogspot.cz/2013/05/presmerovani-roury-bash.html

EDIT: trochu jsem rozepsal tu smyčku, když je konečně čas :)

Diky za perfektni vysvetleni. Tomu \n jsem celkem rozumnel, to znam z meho oblibeneho sedu ;D Ale smycky, roury, to uz tapu... Pro me je to vsechno trochu carovani, ponevadz nemam zadny teoreticky zaklady a vsechno se ucim za pochodu, tak jak zrovna co kdy potrebuju :)

Jeste se zeptam:

Obdobnym zpusobem, jako ta mena ve wgetu by se dalo resit i to vkladani stejneho symbolu na zacatek radky, ze?

Ja jsem jeste premyslel, jak to udelat uzivatelsky prijemnejsim, aby se (pokud chci zmenit stahovane meny) nemusel editovat skript. Nejdriv jsem si myslel, ze by se ty menove kody mohli brat primo z te cilove tabulky, to se tak nejak primo nabizi. Ale pak mi doslo ze to je blbost, protoze ta tabulka je ODS, ne CSV (ktere je snadno citelne i jako text). Samozrejme by se mohla udelat jedna zvlastni, CSVckova jenom s temi kody. Ale to mi zase nepripada moc elegantni... Nejaky napad?

 

Provoz zaštiťuje spolek OpenAlt.