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: awk (nebere vzorek jako filter pro vystup)  (Přečteno 4400 krát)

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
awk (nebere vzorek jako filter pro vystup)
« kdy: 27 Srpna 2008, 11:15:44 »
poprosil bych, jestli by mi nekdo nezanalyzoval nasledujici smycku, kterou jsem obslehl z jedne ucebnice
jedna se vypsani procentualniho podilu kazdeho z cisel z kazdeho radku odpovidajicimu zadanemu vzorci
otazka je, proc mi to zpracuje ve vystupu i radky, pro ktere nesedi vzorec a vypise je s procentualnim podilem  0.00%
sice je umim pak odstranit treba sedem, ale prijde mi to kozi ... :)
Kód: [Vybrat]
awk '/vzorek/ { cislo[NR] = $1
           text[NR] = $0
             suma += $1
        }
END { if (suma)
       for (i=1; i<=NR; i++)
        printf ("%s (%4.2f%%)\n",text[i],100*cislo[i]/suma)
       }' < vstupni soubor
vystup :
 (0.00%)
 (0.00%)
3 vzorek (25.00%)
4 vzorek (33.33%)
5 vzorek (41.67%)
 (0.00%)
 (0.00%)
« Poslední změna: 28 Srpna 2008, 19:56:13 od tomaskCZ »

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #1 kdy: 27 Srpna 2008, 13:55:53 »
pomohlo by, kdybys uvedl ten vzorek a vstupni soubor.

Nicmene uz asi tusim, kde je chyba. V te prvni casti ukladas postupne do pole udaje z radku, jez odpovidaji vzorku (dejme tomu, ten vzorek jsi neuvedl), konkretne pro radky 3, 4 a 5. V druhe casti pak provadis ten vypocet, ale provadis jej tolikrat, kolik bylo radku (tj. 7x).  V pripade, ze radek neodpovidal vzorku, obsahuje prislusny prvek v poli prazdnou hodnotu, ktera se pri vypoctu interpretuje jako nula. Proto ten vysledek.

Resenim by bylo mit vlastni pocitadlo radku, jez vyhovuji vzorku. Tj. do prvni casti dopsat neco jako "vzorku += 1" a v druhe casti v cyklu misto "NR" pouzit ono "vzorku".

Uf, prepisoval jsem to asi petkrat, tak snad je to srozumitelne.
Btw, shodou okolnosti je ten odkaz na prvek v poli "cislo" s indexem "i" povazovan za tag pro kurzivu, proto z textu zmizel a zbytek je kurzivou.
« Poslední změna: 27 Srpna 2008, 14:21:33 od kkaarreell »

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #2 kdy: 27 Srpna 2008, 18:10:16 »
aha, diky, je to napsano srozumitelne

vstupni soubor jsem pro jednoduchost opravdu udelal takto
1
2
3 vzorek
4 vzorek
5 vzorek
6

takze vzorek je ve skutecnosti opravdu vzorek :) /vzorek/

uz se zacinam chytat, 'problem' je v te sekci END, protoze predchozi akce (inkrementace poli) skoncila {} a jede to znovu, myslel jsem, ze to ma omezit ta fraze if (suma), tzn. proved pokud neni honota prazdna
« Poslední změna: 27 Srpna 2008, 18:12:20 od tomaskCZ »

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #3 kdy: 27 Srpna 2008, 18:35:06 »
No, asi takto. Ta prvni cast se provede pro kazdy zpracovavany radek. Promenna NR obsahuje vzdy cislo aktualne zpracovavaneho radku. Problem je v tom, ze po pruchodu prvni casti mas pole "cislo", ve kterem jsou definovany pouze prvky s indexy 3, 4 a 5 (protoze ostatni radky neprosly vyberem).

Sekce END se provadi teprve az se zpracuji vsechny radky. V tuto chvili NR obsahuje cislo posledniho radku, tedy vlastne celkovy pocet radku. Takze v tom cyklu prochazi promenna "i" vsechny  hodnoty od 1 az po NR (tedy 7) a v kazdem pruchodu se provede ten prislusny vypocet. Pro i=1,2,6,7 nejsou prvky v poli "cislo" definovany a proto jsou v tom vypoctu chapany jako nula (odtud ten vysledek).

V te promenne suma je jen celkovy soucet tech cisel, takze nic, co by melo nejaky relevantni vyznam. Pravdepodobne by to zafungovalo jen v pripade, ze by v prvni casti zadny radek neprosel vyberem a proto by se ta cast v podmince neprovedla (mozna taky v pripade, ze by nektera cisla byla zaporna a soucet roven 0, nejsem si uplne jist, jak presne jsou v awku vyhodnocovany podminky).

Jak uz jsem rekl, kdybys to chtel "opravit", tak pouzij dalsi promennou, kterou inkrementujes jen v pripade vyhovujicich radku (prvni cast) a nasledne ji pouzij namisto NR pri tom ukladani do pole. Takze misto na mista 3,4,5 se ulozi v poli na mista 1,2,3. V casti END bude tato promenna vlastne predstavovat pocet spravnych radku, takze ji pouzijes namisto NR jako horni limit v cyklu. A pak uz by to melo fungovat spravne.
« Poslední změna: 27 Srpna 2008, 18:41:20 od kkaarreell »

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #4 kdy: 28 Srpna 2008, 10:57:43 »
Kód: [Vybrat]
awk '/vzorek/ {
                 aaa += 1
           cislo[aaa] = $1
           text[aaa] = $0
              suma += $1
                    }
END { if (suma)
       for (i=1; i<=aaa; i++)
        printf ("%s (%4.2f%%)\n",text[i],100*cislo[i]/suma)
       }'  vstupni soubor
takze takhle to chodi ok, diky za pomoc, puvodni priklad byl pro vsechny radky bez vyberu, proto to NR, uz je to jasny
podminky v awk jsou pro me uplna novinka, doposud jsem to pouzival jenom na selektovani textu,nekdy mi to s tim nedocvakne i kdyz si to prectu v nejakem manualu x-krat :)
« Poslední změna: 28 Srpna 2008, 19:55:30 od tomaskCZ »

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #5 kdy: 28 Srpna 2008, 12:22:30 »
Doporucil bych upravit ty tve zapisky a uzavrit cely kod do tagu "code", protoze jinak je z nich tento nefungujici fragment v kurzive. To jen pro pripad, ze by si to nekdo chtel zkusit a kroutil hlavou, ze mu awk hlasi chybu.

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #6 kdy: 28 Srpna 2008, 20:11:27 »
ok, hotovo

vyuziju jeste tedy k doplnujicimu dotazu : da se do awk podminky cyklu pouzit nejaka externi bashovska promenna ?
napr. bude-li awk uzavrene v dalsi smycce a chtel bych zacatek BEGIN vykonat pouze jednou a to jeste podle vnejsich podminek
tzn. ne znova nechat inicializovat od zacatku pri dalsim kroku smycky while
Kód: [Vybrat]
aaa=2
while read cokoliv; do
   awk  ' BEGIN { if(aaa)                     ## nefunguje ani jako $aaa nebo awk  ' BEGIN { if(' "$aaa" ') 
                  printf ("neco"))
                        }
          /vzorek/' {............

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #7 kdy: 28 Srpna 2008, 21:13:32 »
No, moznosti vyuziti promennych z shellu je vic (aspon dve), ta min nesrozumitelna je definovat pomoci parametru "-v" nove promenne v awk. Snad priklad nize napovi:

Kód: [Vybrat]
$ A=ahoj
$ B=nazdar
$ awk -v varA="$A" -v varB="$B"  '{ printf("%i: %s %s\n", NR, varA, varB)}' test.txt
1: ahoj nazdar
2: ahoj nazdar
3: ahoj nazdar
$
Obsah souboru test.txt neni dulezity, ma proste jen tri radky.

Co se tyce toho vykonani BEGIN pouze jednou, opravdu ma takova sekce smysl? Kazdopadne s pomoci tech promennych a nejake podminky to pujde. Nebo treba ten awk pouzit dvakrat, jednou pred cyklem s BEGIN a pak v cyklu uz bez BEGIN. No vsak si nejak poradis.

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #8 kdy: 29 Srpna 2008, 12:39:47 »
ahoj nazdar :)

jasne, smysl to ma pouze castecny, jenom me to zajimalo - samozrejme lze vykonat i jeste pred vstupem do smycky, to je pravda
jinak nize(ci spis vyse) uvedeny postup s promnenymi nefunguje(alespon co jsem zkousel) pro podminky cyklu, ale presne pro toto pouziti v printu,ci vzorku - to uz mam vyzkouseno predtim -nicmene neni dulezite.

Diky
« Poslední změna: 29 Srpna 2008, 12:44:04 od tomaskCZ »

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #9 kdy: 29 Srpna 2008, 13:15:04 »
jinak nize(ci spis vyse) uvedeny postup s promnenymi nefunguje(alespon co jsem zkousel) pro podminky cyklu, ale presne pro toto pouziti v printu,ci vzorku - to uz mam vyzkouseno predtim -nicmene neni dulezite.
Hm, tomu nerozumim. Muzes to nejak upresnit, jak to myslis? Ve tom fragmentu, co jsi napsal, jsi pouzil promennou v podmince. S tim neni zadnej problem.

Kód: [Vybrat]
$ cat test.txt
1
2
3
4
5
$ A=2
$ awk -v prom=$A '{ if ($1>prom) print }' test.txt
3
4
5


tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #10 kdy: 31 Srpna 2008, 20:58:11 »
fakt, ze to opravdu funguje, jak jsi napsal. Puvodni problem byl, ze jsem si to zkousel poprve v praci na Solarisu, kde je awk jine verze, chybi prepinac -v a promenne se definuji na konec za vyraz - tam to na promenne dane do cyklu ohled nebere, nicmene funguji v printech.

Druhy problem byl, kdy jiz testovano na ubuntu - jsem musel podminku definovat znovu a znovu pred kazdy printf, coz me prve zmatlo a vypadalo to, ze to nereaguje

pr.
Kód: [Vybrat]
hodnota=1
   awk  -v aa=$hodnota ' BEGIN { if(aa<2)
                  printf (" BOARD\n")
if(aa<2)

                  printf ("USAGE(%%)   NUMBER       TYPE\n")
if(aa<2)

                  printf ("--------------------------------------------------------\n")
if(aa<2)

                  printf ("............  %%\n")

atd.

........
hodnota=`expr $hodnota + 1`;echo $hodnota

« Poslední změna: 31 Srpna 2008, 21:00:58 od tomaskCZ »

kkaarreell

  • Stálý člen
  • **
  • Příspěvků: 1072
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #11 kdy: 31 Srpna 2008, 21:51:38 »
Druhy problem byl, kdy jiz testovano na ubuntu - jsem musel podminku definovat znovu a znovu pred kazdy printf, coz me prve zmatlo a vypadalo to, ze to nereaguje
:-D proc myslis, ze tam jsou ty slozene zavorky?
Kód: [Vybrat]
awk -v prom=$A '{ if ($1>prom) {print;print} }' test.txt

tomaskCZ

  • Aktivní člen
  • *
  • Příspěvků: 373
Re: awk (nebere vzorek jako filter pro vystup)
« Odpověď #12 kdy: 02 Září 2008, 10:32:53 »
heste jedny .... ahaa :)

 

Provoz zaštiťuje spolek OpenAlt.