Nowe posty

Autor Wątek: Awk i regexp.  (Przeczytany 4559 razy)

dfens

  • Gość
Awk i regexp.
« dnia: 2010-12-06, 00:28:12 »
Cześć!

Muszę przeanalizować kod źródłowy programu w C. Chodzi o ilość zadeklarowanych funkcji, ilość wywołań oraz wypisanie nazwy i liczby argumentów każdej z nich.

Do tego używam wyrażeń regularnych, jednak chyba coś jest z nimi nie tak, bo skrypt nie odnajduje poprawnie w/w rzeczy.

Funkcje w programie są w postaci, np:

void insert2 ( char name, int counter );
double draw_line (float x1, float x2, int name );

Wywołanie:

insert2 (costam, 5);

itd.

Moje wyrażenia regularne:

- Do odnajdywania deklaracji funkcji:

^(void|int|float|double)[:space:][A-Za-z0-9][:space:]\\([^#$%]\\);$

- Do odnajdywania wywołań funkcji:

^[A-Za-z0-9][:space:]\\([^#$%^]\\);$

Odnajdywanie argumentów to podobnie, potem wyłuskuje za pomocą $x odpowiedni argument i ucinam przecinek.

Te wyrażenia z pewnością są błęde, ale nie wiem jak to naprawić...


Z góry dzięki za pomoc.

  • Gość
Awk i regexp.
« Odpowiedź #1 dnia: 2010-12-06, 00:35:00 »
Załóż, że mogą być wielokrotne spacje, przed po i w linii, załóż, że może być wiele parametrów... O ile dobrze pamiętam to w regexp jest możliwość doboru odpowiedniej ilości wystąpień chyba coś ala [:space:]{1,4} powinno akceptować od 1 do 4 spacji

Poczytaj man awk

arctgx

  • Gość
Awk i regexp.
« Odpowiedź #2 dnia: 2010-12-06, 00:41:54 »
Na pierwszy rzut oka:
Cytat: dfens
^(void|int|float|double)[b][:space:][A-Za-z0-9][:space:][/b]\\([^#$%]\\);$
Pogrubione miejsce to dokładnie jeden znak z zakresu [A-Za-z0-9] otoczony białymi znakami z obu stron. Może przy odrobinie szczęścia trafisz na funkcję o jednoznakowej nazwie (swoją drogą, nie wiem czy pierwszym znakiem funkcji w C może być liczba). Dodaj operator wystąpienia tego znaku co najmniej raz.

P.S. W man 7 regex możesz znaleźć coś ciekawego.

dfens

  • Gość
Awk i regexp.
« Odpowiedź #3 dnia: 2010-12-06, 00:42:58 »
Ok dodałem +. Jednak nadal nie wyszukuje mi funkcji.

Problem tkwi na pewno w tym, że nie wiem jak dopasować te void, int, float, double na początku łańcucha. W manie nie znalazłem nic , co by mi w tym pomogło.

arctgx

  • Gość
Awk i regexp.
« Odpowiedź #4 dnia: 2010-12-06, 00:58:38 »
Chyba wiem, w czym jeszcze problem:
Cytat: man awk
A character class is only valid in a regular expression inside  the  brackets  of  a  character  list.
Kiedy zamieniłem [:space:] na [[:space:]], dopasowanie zadziałało.

P.S.
1. Plus powinien zadziałać.
2. Łatwiej byłoby Ci zaczynać filtrowanie od prostych wyrażeń, np. '/^(void|int)/', a dopiero później dopisywać warunki dla reszty wyrażenia.

dfens

  • Gość
Awk i regexp.
« Odpowiedź #5 dnia: 2010-12-06, 01:07:56 »
Dla funkcji:

void wczytaj (char czesc, int numer);

Wyrażenie:

^(void|int|float|double)[[:space:]]+[A-Za-z0-9]+[[:space:]]+\\([^#$%]+\\);$

Nie działa...


//edit

No ja tak robie, ale koniec końców muszę w końcu napisać całe...

arctgx

  • Gość
Awk i regexp.
« Odpowiedź #6 dnia: 2010-12-06, 01:09:09 »
Jak wyżej zdążyłem dopisać, uprość wyrażenie na początek.

dfens

  • Gość
Awk i regexp.
« Odpowiedź #7 dnia: 2010-12-06, 01:12:15 »
Czekaj, bo chyba nie rozumiem. Uproszczenie do ^(void|int)/', nic mi nie daje, bo wtedy awk wyszukuje mi też deklaracje zmiennych np. int variable;

Chodzi ci o to żebym jakoś to rozdzielił na kilka etapów?

arctgx

  • Gość
Awk i regexp.
« Odpowiedź #8 dnia: 2010-12-06, 01:16:41 »
No jasne, że nie daje i to tylko przykład. Zerknij:
 $ cat /tmp/g.c 
void insert2( char name, int counter );
void insert2 ( char name, int counter );
voidinsert2 ( char name, int counter );
void i ( char name, int counter );
 $ awk '/^(void|int|float|double)[[:space:]]/' /tmp/g.c
void insert2( char name, int counter );
void insert2 ( char name, int counter );
void i ( char name, int counter );
 $ awk '/^(void|int|float|double)[[:space:]][A-Za-z0-9]/' /tmp/g.c
void insert2( char name, int counter );
void insert2 ( char name, int counter );
void i ( char name, int counter );
 $ awk '/^(void|int|float|double)[[:space:]][A-Za-z0-9]+[[:space:]]/' /tmp/g.c
void insert2 ( char name, int counter );
void i ( char name, int counter );
 $ awk '/^(void|int|float|double)[[:space:]][A-Za-z0-9][[:space:]]/' /tmp/g.c
void i ( char name, int counter );
i tak dalej, aż po dolar.

Reszty nie przeglądałem.

P.S. Dla porządku dodałem jeszcze jedno wyrażenie bez plusa.

dfens

  • Gość
Awk i regexp.
« Odpowiedź #9 dnia: 2010-12-06, 01:26:19 »
awk '/^[\\s\\t\\r\\n]?(void|int|float|char)[[:space:]][A-Za-z0-9]+[[:space:]]\\([^$#%]+\\)\\;$/ '
Tak działa :) Wielkie dzięki za pomoc. Miłej nocy.