Вырезание комментария в bash скрипте.

Задача вырезания комментариев из bash-скрипта очень сложна: дело в том, что допустимо использовать 2 вида кавычек, причём внутри кавычек не работают другие кавычки и # не является началом комментария. Кроме того, в двойных кавычках могут быть экранированные двойные, а в одиночных - не могут. Закавыченные блоки могут расползтись на несколько строк. И ещё вне кавычек так-же могут встречаться экранированные кавычки и #.

Основная идея скрипта - сохранить строку (строки) в области удержания, и отрезать в строке всё до начала комментария. После чего можно удалить найденный комментарий из строки (как при поиске одинаковых подстрок). Все строки бывают 6и видов:

  1. Строки начинающиеся с любого символа кроме «'», «"», «#», и «\». В этих строках я удаляю все первые символы до первого спец-символа, и строка становится одной из 2,3,4,5 или 6го типа.
  2. Строки которые начинаются на «\» - это какой-то экранированный символ - его можно удалить, и снова проверить тип получившейся строки.
  3. Строки которые начинаются на «#», это начала комментария, и можно его отрезать.
  4. Пустые строки - значит комментария нет, и строку можно печатать.
  5. Строки которые начинаются на одиночную кавычку «'» - если в строке есть ещё одна одиночная кавычка, всё что между ними можно резать, и их тоже. Если второй кавычки нет, то нужно загрузить ещё одну строку, и продолжить анализ. Текущая строка нам не нужна, можно в новой строке вставить в начало одиночную кавычку, и продолжить анализ.
  6. Строки начинающиеся с двойной кавычки «"». Обрабатываются как и строки типа 5, однако есть тонкость - возможен случай, когда внутри двойных кавычек есть экранированная двойная кавычка - она не является концом блока и удаляется.

Вот сам скрипт:

Пример 4.11. Удаление комментариев в bash-скрипте.

#!/bin/sed -rf

# сохранение строки
h

:begin_loop
	# p
	# удаление обычного начала
	s/^[^'"#\]+(.*)/\1/
	t begin_loop
	# удаление экранированных символов
	s/^\\.//
	t begin_loop
	# удаление закавыченного блока
	s/^'[^']*'//
	t begin_loop
	s/^'.*//
	T lq
		# незакрытый блок кавычек, необходима подгрузка
		${
			x
			b end
		}
		n
		H
		s/^/'/
		t begin_loop
	:lq
	# удаление экранированной кавычки внутри закавыченного блока
	s/^"[^"]*\\"/"/
	t begin_loop
	# удаление закавыченного блока
	s/^"[^"]*"//
	t begin_loop
	s/^".*//
	T lq2
		${
			x
			b end
		}
	n
	H
	s/^/"/
	t begin_loop
	:lq2
	/^\#/{
		# теперь строка начинается с #
		H
		x
		s/^(.*)(\#[^\n]*)\n\2$/\1/
		b end
	}
	# а коммента и нету
	x

	:end
# s/.*/\x1b[32m'&'\x1b[0m/


Вы можете обсудить этот документ на форуме. Текст предоставляется по лицензии GNU Free Documentation License (Перевод лицензии GFDL).

Вы можете пожертвовать небольшую сумму яндекс-денег на счёт 41001666004238 для оплаты хостинга, интернета, и прочего. Это конечно добровольно, однако это намного улучшит данный документ (у меня будет больше времени для его улучшения). На самом деле, проект часто находится на грани закрытия, ибо никаких денег никогда не приносил, и приносить не будет. Вы можете мне помочь. Спасибо.