It's fairly straightforward with awk, perhaps doable with sed.
With awk, you would have a state that gets set/reset on each typedef line, and concludes on each line with a right curly brace. A suitable awk script would look like
BEGIN {
state = 0;
typedef="";
fields="";
}
/typedef[ ]+struct/{
state = 1;
typedef=$3;
next;
}
/}.*;/ {
if (state != 0) {
sub("^.*}[ ]*","",$0);
sub(";","",$0);
sub(",$","",fields);
printf "%s %s: %s\n", typedef, $0, fields;
state = 0;
fields = "";
typedef = "";
}
next;
}
(state == 1){
gsub("[ ]+"," ", $0);
gsub(";",",",$0);
fields = fields $0;
next;
}
where the [ and ] brackets enclose a space and tab (to make it portable). There are four parts to the script:
- the
BEGIN action initializes variables (not strictly necessary, but some awks do slightly different things with uninitialized variables)
- the pattern matching the line with
typedef, followed by blank(s) and the word struct. That expects at least 3 fields on the line, using the third as the name of the typedef.
- a pattern to match the closing curly brace. Just in case your file has other stuff in it, the action checks if
state was set. The $0 is the current line. The first substitution trims away everything before the word we're interested in, and the second trims away the semicolon following it. The third substitution changes a comma after the fields variable that came from the 4th action (below), to an empty string.
- a pattern matching all other lines when
state is set. Like the previous action, this uses substitution to trim away the parts not wanted, first by reducing multiple blanks to a single blank, and then changing the trailing semicolon to a comma.
Call that file foo.awk, and your input data foo.in, to use awk like this:
awk -f foo.awk <foo.in
If you wanted to match lines like this:
struct foo {
rather than
typedef struct foo {
then the pattern could be written
/^([ ]*typedef)?[ ]+struct[ ]+/{
(again, with a literal space and tab in the square brackets). The parentheses mark a group and the question mark ? says to repeat that zero-or-more times. (The { on the line actually denotes the beginning of the action, but I left it there to match the line in the given script).
Further reading: