Интерактивная sed.

Вступление.

Вот в VIM'е можно задать команду :s/i/Z/gc, что приведёт к тому, что vim будет спрашивать после каждой команды подтверждения. Это всё отлично, но как быть, если хочется подтверждения от sed? Ишь чё захотели! sed - неинтерактивный редактор, а значит нифига у вас не получится!

И тем не менее: стал-бы я делать новую главу, если-бы мне нечего было сказать? Нет конечно! На самом деле, sed может всё. В том числе и стать интерактивной. Просто нужно уметь её готовить ;-) Итак, для начала разберёмся с проблемами, которые нас подстерегают.

Почему не получается использовать sed в интерактивном режиме?

На самом деле проблема всего одна, но она практически непреодолимая: мы имеем два выходных потока (стандартный, и поток ошибок), но входной поток всего один. Спрашивается, откуда sed узнает, что юзверь собственно хочет? Это в принципе можно обойти: достаточно кормить sed файлами, и заставить её внутри скрипта читать команды от юзера из стандартного входного потока. Команда r нам не подходит, ибо она хоть и неплохо читает, но совсем не туда пишет (нам надо писать во внутренний буфер, а она пишет в выходной поток). Но можно использовать ту-же read из bash. Читать можно из файла /dev/fd/0. Однако, я даже и рассматривать этот вариант не буду (во всяком случае, не сегодня). Есть способ лучше: использовать GUI.

GUI и sed, или как я скрестил ежа с ужом.

Сам заголовок довольно неожиданный, вам не кажется? А тем не менее, ничего сложного тут нет: существуют аж 3 программы (как минимум) позволяющие прикрутить к CLI GUI. Я не стану рассматривать самую примитивную из них - xmessage, а сразу перейду к утилитке gmessage. Это довольно простая утилитка, и тем не менее, её возможностей нам вполне хватит. Как видно из названия, утилита выводит сообщение юзеру. Как из названия не видно, она ещё и ожидает его ответа. По умолчанию имеется лишь одна кнопка "ОК", но это только по умолчанию. Приступим к её настройке:

Настройка gmessage.

Сначала gmessage надо установить (если она конечно не установлена), эта утилитка входит в состав GTK, но её можно скачать и отдельно. Как её ставить - без понятия, у меня есть пакет для Slacky, который я собрал ещё для Slackware 10.2, и который, тем не менее, отлично работает и сегодня, в 13й слаке. Пользователи других дистрибутивов несомненно лучше меня знают, как ставить пакеты в их любимой ОС. А настраивается эта утилитка как обычно: копируем в свой домашний каталог настроечный файл:

					$ cp /usr/local/share/gmessagerc ~/.gmessagerc
				

А теперь его правим. Впрочем править там особо и нечего, достаточно выбрать какой-нить фонт, лично я выбрал первый попавшийся моноширный (только надо брать именно моноширный!, а то жутко не удобно этим пользоваться, хотя и красиво). Вообще говоря, фонты дело субъективное, и тут вы сами выбирайте, кому что нравится. Теперь запустим программу:

					$ gmessage 'Hello World!'
				

Мы увидим что-то вроде:

Рисунок 4.15. Проверка работы gxmessage.

Проверка работы gxmessage.


Конечно оформление окошка будет сделанно по вашему вкусу. Теперь посмотрим, что ещё умеет эта софтина:

$ gmessage --help
Usage:	gmessage [OPTIONS] string...
		gmessage [OPTIONS] --file filename|-
Displays STRING or the contents of FILENAME in a window.

	--file filename          file to read from, "-" for stdin.
	--buttons string         comma-separated list of label:exitcode.
	--default button         button to activate if Return is pressed.
	--title title            title for main window.
	--print                  print the button label to stdout when selected.
	--center                 pop up at center of screen.
	--nearmouse              pop up near mouse cursor.
	--timeout secs           exit after "sec" seconds with default status.
	--help                   print this message and exit.
	--version                show version information and exit.

All options may be specified with "-" instead of "--", for
compatibility with xmessage.
If a file is used, non option arguments are not accepted.
The center option overrides nearmouse.
				

В принципе, вполне достаточно для наших целей.

Замечание

Да, забыл сказать: возможно у вас не заработают русские буквы - это связано с набором фонтов. У меня вот что-то не нашлось юникодного фонта, пришлось использовать koi8-r, и перекодировать при необходимости. Возможно плохо искал...

Интерактивный скрипт на sed.

Я специально взял очень простую задачу: заменить буквы «i» на «Z», вы безусловно переделаете как оно вам надо, это уже частности. Сам скрипт получился совсем простой:

Пример 4.21.

sub.sed
#!/bin/sed -rf

/i/{
	h
	s/.*/Old string: '&'/w sub.tpl
	g
	s/i/Z/g
	s/.*/New string: '&'/w sub.tpl
	s/.*/Substitute?/w sub.tpl
	s~.*~gmessage --file sub.tpl --title sub.sed --buttons Yes:0,No:67,Cancel:68; echo $?~e
	/^0$/{
		g
		s/i/Z/g
		b
	}
	/^67$/{
		g
		b
	}
	Q
}

					


Основная идея скрипта: создать шаблон, который потом отдаётся команде gmessage, и выводится на экран. Шаблон (sub.tpl создаётся при первом совпадении, используя модификатор w команды s.

Замечание

В info sed про этот модификатор сказано, что файл усекается перед записью до нулевой длинный, на самом деле, это не совсем так: файл усекается лишь при первой записи, далее sed добавляет туда строчки.

В шаблон записываются всего три строчки: старая строка, новая, и собственно вопрос. При этом старые строки не удаляются. Юзеру доступны три кнопки: да, нет, и отмена. Выглядит это примерно так:

Рисунок 4.16. Интерактивная замена sed.

Интерактивная замена sed.


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

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