Вместо sed
, всегда можно было использовать в режиме awk
поле каждого символа (FS=""
):
awk 'BEGIN {
RS = "\n" ;
FS = "" ;
d = 0 ;
}
{
for (i=1; i<=NF; i++)
if ($i == "{") {
d++ ;
if (d == 1) printf "{\n"
} else
if ($i == "}") {
d-- ;
if (d == 0) printf "}"
} else
if (d == 0)
printf "%s", $i ;
if (d == 0) printf "\n"
}' INPUT-FILE(s)...
выше будет пропускать содержимое любых парных фигурных скобок, т.е.функции и структуры, инициализации массива и т. д. и вывод результата в стандартный вывод. Вы можете указать один или несколько файлов. (Если вы не укажете какие-либо файлы, он будет ожидать ввода со стандартного ввода.)
Как и сейчас, он будет запутаться в фигурных скобках в кавычках или комментариях. Это можно было бы зафиксировать точно так же, но это довольно быстро. Это всего лишь взломать, чтобы доставить вам удовольствие.
Я добавил точки с запятой (;
), чтобы вы могли просто набить все в приведенном выше фрагменте на одной длинной командной строке.
Логика сценария очень проста. Он использует пустой разделитель полей (FS
), так что каждый символ ввода будет своим собственным полем. Правило BEGIN
запускается один раз перед обработкой любого ввода и устанавливает это. Для информации разработчика я также инициализирую d = 0
, хотя это не обязательно для awk, так как предполагается, что неинициализированные переменные будут пустыми или нулевыми, если это необходимо. Он будет отслеживать текущую глубину привязки для каждого входного символа.
Второе сжатое выражение будет выполняться один раз за каждую запись. Поскольку я устанавливаю RS = "\n"
, каждая строка является отдельным выражением. Таким образом, он будет выполняться один раз для каждой строки ввода. Из-за FS = ""
каждый символ в этой строке будет отдельным полем. Подписей нет NF
Поля в записи: $1
, $2
, .., $(NF-1)
, и $NF
. Предложение из трех частей if просто выводит внешние фигурные скобки и все, что не входит в фигурные скобки (то есть когда d == 0
).
Можно расширить эту awk
скриптлета, чтобы охватить комментарии, строки символов константы (используйте \047
для обозначения одной цитаты, если вы не поставить скрипт в отдельный файл с #!/usr/bin/awk -f
), и обрабатывать или игнорировать препроцессор макросы ,
Это немного сложно, и вы получите несколько сотен строк awk-скрипта, но он должен быть достаточно надежным и достаточно быстрым. Причина, по которой это возможно, состоит в том, что правила токенизации в C в данном конкретном случае легко следовать; Я лично использовал бы полномасштабный C lexer (лексический анализатор или сканер) во всех других случаях использования. И, вероятно, для этого тоже.
Если вы хотите использовать полноэкранный C lexer, в сети есть множество доступных в сети, но вам нужно будет использовать язык более высокого уровня, такой как C или C++. Если вы хотите обрабатывать все угловые случаи, для этого потребуется также использовать препроцессор C/C++, но эти правила легки (даже с awk).
Вы должны объяснить, почему вы спрашиваете об этом. –