Обработка текста для извлечения полей структуры

Например, я пытаюсь извлечь поля из структуры.

typedef struct newstruct { long id; uint32_t vtid; struct HN* next; } HashNode; 

Я хочу использовать sed / awk для извлечения имени структуры, а затем поля с разделителем как

 newstruct HashNode: long id, uint_32 vtid, struct HN* next 

Это довольно просто с awk , возможно, с sed .

С awk вас будет состояние, которое будет установлено / сброшено на каждой строке typedef , и заканчивается на каждой строке правой фигурной скобкой. Подходящий awk скрипт будет выглядеть так:

 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; } к 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; } к 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; } 

где [ и ] скобки заключают в себе пробел и вкладку (чтобы сделать ее переносимой). В скрипте есть четыре части:

  1. действие BEGIN инициализирует переменные (не обязательно, но некоторые awks делают несколько разные вещи с неинициализированными переменными)
  2. шаблон, соответствующий строке с typedef , за которым следует пробел (s) и слово struct . Это ожидает как минимум 3 поля в строке, используя третье имя имени typedef.
  3. шаблон для соответствия закрывающей фигурной скобке. На всякий случай, если в вашем файле есть другие вещи, действие проверяет, было ли установлено state . $0 – текущая строка. Первая подстановка отбрасывает все до слова, которое нас интересует, а второе отделяет точку с запятой, следуя за ней. Третья подстановка изменяет запятую после переменной fields которая пришла из 4-го действия (ниже), в пустую строку.
  4. шаблон, соответствующий всем другим строкам, когда state установлено. Как и предыдущее действие, это использует подстановку, чтобы обрезать части, которые не нужны, сначала уменьшая несколько пробелов до одного пробела, а затем изменяя конечную точку с запятой на запятую.

Назовите этот файл foo.awk и ваши входные данные foo.in , чтобы использовать awk следующим образом:

 awk -f foo.awk <foo.in 

Если вы хотите совместить такие строки:

 struct foo { 

скорее, чем

 typedef struct foo { 

то шаблон может быть записан

 /^([ ]*typedef)?[ ]+struct[ ]+/{ 

(опять же, с буквальным пространством и вкладкой в ​​квадратных скобках). Скобки обозначают группу и знак вопроса ? говорит повторить, что ноль или больше раз. ( { На линии фактически обозначает начало действия , но я оставил его там, чтобы соответствовать строке в данном скрипте).

Дальнейшее чтение:

  • awk – язык сканирования и обработки шаблонов (POSIX)
  • 9.4 Расширенные регулярные выражения (POSIX)
 sed -rn ' /typedef struct ([[:alnum:]_]+)\s+\{/!b s//\1/; h :X n /}\s+([[:alnum:]_]+)/{ s//\1/ H g s/;//g s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/\1 \5: \2, \3, \4/ p;b } s/\s*(.+);\s*/\1/ H bX ' file newstruct HashNode: long id, uint32_t vtid, struct HN* next , sed -rn ' /typedef struct ([[:alnum:]_]+)\s+\{/!b s//\1/; h :X n /}\s+([[:alnum:]_]+)/{ s//\1/ H g s/;//g s/(.*)\n(.*)\n(.*)\n(.*)\n(.*)/\1 \5: \2, \3, \4/ p;b } s/\s*(.+);\s*/\1/ H bX ' file newstruct HashNode: long id, uint32_t vtid, struct HN* next