
Например, я пытаюсь извлечь поля из структуры.
typedef struct newstruct {
long id;
uint32_t vtid;
struct HN* next;
} HashNode;
Я хочу использовать sed/awk для извлечения имени структуры, за которым следуют поля с разделителем, например
newstruct HashNode: long id, uint_32 vtid, struct HN* next
решение1
Это довольно просто с 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
инициализирует переменные (это не обязательно, но некоторые awk делают немного другие вещи с неинициализированными переменными) - шаблон, соответствующий строке с
typedef
, за которым следуют пробел(ы) и словоstruct
. Это ожидает не менее 3 полей в строке, используя третье в качестве имени typedef. - шаблон, соответствующий закрывающей фигурной скобке. На всякий случай, если в вашем файле есть что-то еще, действие проверяет, было ли
state
установлено.$0
Текущая строка. Первая подстановка обрезает все перед интересующим нас словом, а вторая обрезает точку с запятой после него. Третья подстановка изменяет запятую после переменной,fields
которая пришла из 4-го действия (ниже), на пустую строку. - шаблон, соответствующий всем остальным линиямкогда
state
установлено. Как и предыдущее действие, это действие использует замену для удаления ненужных частей, сначала сокращая несколько пробелов до одного, а затем изменяя конечную точку с запятой на запятую.
Назовите этот файл foo.awk
и ваши входные данные foo.in
, чтобы использовать awk следующим образом:
awk -f foo.awk <foo.in
Если вы хотите сопоставить строки следующим образом:
struct foo {
скорее, чем
typedef struct foo {
тогда шаблон может быть написан
/^([ ]*typedef)?[ ]+struct[ ]+/{
(опять же, с буквальным пробелом и табуляцией в квадратных скобках). Скобки обозначаютгруппаа вопросительный знак ?
говорит, что это нужно повторить ноль или более раз. ({
на линии фактически обозначает началодействие, но я оставил его там, чтобы он соответствовал строке в данном скрипте).
Дальнейшее чтение:
решение2
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