Fórum Ubuntu CZ/SK

Ubuntu pro osobní počítače => Software => Příkazový řádek a programování pro GNU/Linux => Téma založeno: dadam 21 Února 2010, 23:04:50

Název: Regulární výrazy
Přispěvatel: dadam 21 Února 2010, 23:04:50
Zdravím,
mám URL, např. http://forum.ubuntu.cz:80/index.php, a potřeboval bych z toho dostat údaje potřebné pro vytvoření a odeslání HTTP požadavku. Mělo by se to provést přes regulární výrazy. Zkoušel jsem funkce regex (http://www.gnu.org/s/libc/manual/html_node/Regular-Expressions.html#Regular-Expressions) nicméně ty mě nevyhovují v tom, že pokud chci získat řekněme jméno serveru, tak výraz
Kód: [Vybrat]
(http://)?[^/:]*
mi označí (doufám, začínám s tím a netestoval jsem to) adresu i s řetězcem "http://". Co s tím? Uvažoval jsem o použití sedu, zpracovat a nechat si vypsat potřebné údaje oddělené mezerami, nicméně se mi moc nechce používat popen() (připadne mi to jako relativně špatně ošetřitelný postup) a nějaký sed api jsem taky nenašel. Naprosto ideální by byla nějaká funkce, která by načetla řetězec, prohnala ho regulárním výrazem a vrátila jen hodnoty která já definuji.
Název: Re: Regulární výrazy
Přispěvatel: starenka 22 Února 2010, 00:24:44
grep defaultne vraci celou radku, mozna tam byl problem. zkus to pustit s -o

(na regular jsem nekoukal)
Název: Re: Regulární výrazy
Přispěvatel: dadam 22 Února 2010, 09:09:31
Grep? Ten tu nepoužívám
Název: Re: Regulární výrazy
Přispěvatel: starenka 22 Února 2010, 09:15:34
No zrejme je jasny, ze dlas v c jen tobe ;)
Název: Re: Regulární výrazy
Přispěvatel: dadam 22 Února 2010, 11:09:36
Máš pravdu, omlouvám se, zapomněl jsem zmínit že to dělám v céčku.
Název: Re: Regulární výrazy
Přispěvatel: jfoot 22 Února 2010, 12:01:59
Zdravím Vás,

jen si dovolím doplnit starenku,  tímto jej zdravím... :):

pokud bude  struktura parsovaných řetězců statická, tedy budou vždy typu : "hhtp://neco_1/neco_2/......../neco_n",
je jedno z řešení je provést "rozsekání" vstupního řetězce na tokens, podle zvoleného delimiteru.

Mělo by se to provést přes regulární výrazy.

To je možné, pokud je k dispozici  c knihovna, která poskytuje metodu typu split. Té se předhodí parsovaný řetězec,
předhodí se jí dále hodnota delimiteru (jako regulární výraz) a ona vrátí pole tokens (řetězců).  Pokud byste na řetězec
http://forum.ubuntu.cz:80/index.php,  aplikoval delimiter "/", tak by split měl vrátit : String tokens [] ={"hhtp:", "", "forum.ubuntu.cz:80","index.php,"}. Při statické struktuře je jméno serveru vždy na tokens[2], tedy zde je jím forum.ubuntu.cz:80

Pokud netrváte na použití regexu, tak obdobnou funkčnost, pokud se nepletu, jako split poskytuje c metoda
 char *strtok( char *str1, const char *str2 );
Název: Re: Regulární výrazy
Přispěvatel: dadam 22 Února 2010, 13:02:30
Ona tam statická struktura nebude. "http://" je volitelné, zápis portu je taky volitelný, může se klidně jednat jen o řetězec "forum.ubuntu.cz". Chápu to tedy tak, že žádná knihovna, která by poskytovala funkce sedu (stačila by např. jedna funkce: int sed (char *re, char *input, char *output, size_t output_length)) neexistuje?
Název: Re: Regulární výrazy
Přispěvatel: pajus 24 Února 2010, 11:39:09
# include <regex.h>
http://www.opengroup.org/onlinepubs/007908799/xsh/regex.h.html

ja to s nimy resim v pohode :)

podivej se na struktury.
  regex_t re
  regmatch_t 
a funkci regexec()

pak napises vyraz treba char *patter="^(http://)?(www.ubutnu.cz)(:80)?$"
po funkci regexec() se ti do struktury regmatch se ti pak ulozi ukazatele na konec a na zacatek hledanych casti - ty ve vyrazu zavorkujes...
Název: Re: Regulární výrazy
Přispěvatel: dadam 24 Února 2010, 13:44:52
Na regex už jsem se díval, ale o tom závorkování jsem nevěděl, děkuju, k++. Možná jsem něco blbě pochopil, ale dá se nějal zjistit, kolik podvýrazů bylo rozpoznáno? Resp. kolik struktur regmatch_t je naplněno validními údaji? Zatím jsem to nikde nenašel....
Název: Re: Regulární výrazy
Přispěvatel: pajus 24 Února 2010, 18:26:37
regmatch_t  pmatch[3];

if(pmatch[1].rm_eo - pmatch[1].rm_so != 0) // pokud  sem nasel prvni uzavorkovanou cast tak rozdil tech ukazatelu je nenulovy tzn ukazuji stejne a nic se nenaslo. zadny podretezec

Jinak samozrejme musis mit regvyraz prelozeny a spravne porovnany funkce regcomp() a regexec().
Doufamze je to ono co jsi myslel :)
Název: Re: Regulární výrazy
Přispěvatel: dadam 25 Února 2010, 00:30:51
Dá se nějak zařídit, aby se určitý uzávorkovaný výraz nezapisoval do regmatch? Třeba počáteční http:// tam nepotřebuju... (Důvod je jiný, nicméně toto je jednodušší)
Název: Re: Regulární výrazy
Přispěvatel: Yur4Y 25 Února 2010, 15:17:28
Myslím, že zápisom (?:http://).
Název: Re: Regulární výrazy
Přispěvatel: dadam 25 Února 2010, 16:11:31
Výcuc ze zdrojáku:
Kód: [Vybrat]
char regexp[] = "(?:http://)";
error = regcomp(&compiled, regexp, REG_EXTENDED);

A výstup z programu:
Kód: [Vybrat]
adam@loki:~/programovani/regexp$ ./main http://www.google.cz/dir/file.fil
Invalid preceding regular expression
Název: Re: Regulární výrazy
Přispěvatel: pajus 25 Února 2010, 17:26:40
Kód: [Vybrat]
char *regexp ="^(http://)?.*$";bacha na to melo by tam byt i ukonceni v tom regexp - coz je vzorek podle ktereho reg vyraz hledas. cili zacina http a ktere je volitelne '?' a pak pokracuje libovolnymi znaky az do konce '$'