Использование регулярных выражений ненадежно, вдвойне не с egrep, если вы не следуете некоторым соглашениям и не делаете ничего слишком сложного.
Рассмотрим:
void *
function(
int a,
void (*pointer)(const char *, int, double),
double d
)
Это объявление распространяется на 6 строк, и egrep просматривает только одну строку за раз.
Это объявление содержит 5 запятых и 3 параметра.
Если вы наложите достаточное количество ограничений на код, который вы ищете, вы, вероятно, получите приблизительное значение к тому, что вы ищете, но C и C ++ очень сложно анализировать. И я даже не думаю о макросах, которые вызывают функцию для вас.
Предлагаемое вами решение имеет ряд недостатков, даже после решения проблемы с посторонними обратными слешами (правильно диагностирован Тимом Пицкером):
egrep "find" * | egrep "\([^,]*,[^,]*,[^,]*\)"
Это откроет такие строки, как:
find(1, 2, 3);
int extra_find(int a, int b, int c) { ... }
extraordinary(find, 3, 21);
printf("find: %.*s\n", 13, "heliotrope");
for (find(1); printf("%d %d\n", 1, 2); x++)
for (x(find, 1); b < max(c, d); i++)
/* find(1,2,3) */
Только одним из них является определение функции, и это все еще не тот выход, который вы хотели.
Если вы можете играть с Perl (или Python) или любым инструментом с PCRE (регулярными выражениями, совместимыми с Perl) или аналогичными, то вы можете сделать что-то, например, убедиться, что на одной строке появляется слово «найти» с последующим открытием скобка, последовательность значений «имя типа», разделенных запятыми и пробелами, и закрывающая скобка.
perl -ne 'print if m/\bfind\s*\(\w+\s+\w+(\s*,\s*\w+\s+\w+){2}\s*\)/'
Но это не относится к указателям, массивам, квалификаторам, таким как 'const', или указателям на функции (или ссылкам, если вы используете C ++), или структурам, на которые ссылается "struct somename varname", или определениям функций, защищенным от макросов расширение (int (getchar)(int c)
) или ... И оно по-прежнему не различает объявления и определения!