sed
Случайные числа в Sed
После шахмат на «Седе» я, похоже, в глазах общественности стал
В основном, задачи очень простые и даже рутинные, ничего интересного, но вот вчера прислали действительно интересный вопрос. Вопрос в том можно ли командами «Седа» получить случайное число?
Уж не знаю что именно такого спросивший собирается с ним потом делать, надеюсь,
Итак, что же можно сделать? Команды жёстко заданы и менять их нельзя, возможно
Я
Тогда я не обратил на это должного внимания, а когда получил упомянутое письмо — вспомнил. Общая идея оформилась быстро: нужно очистить экран, скрыть курсор, выставить цвет фона и шрифта одинаковыми (чтобы скрыть прочитанный из файла мусор — ведь sed выведет прочитанное на экран), прочитать файл случайных чисел, потом сосчитать позицию в которой оказался курсор, восстановить параметры экрана и вывести позицию курсора.
В манипуляциях с экраном ничего сложного нет — существуют специальные управляющие последовательности при помощи которых это делается, даже координаты курсора можно получить ими же.
Получившийся код вполне уверенно работает, разве что у чисел, которые выводятся, распределение далековато от равномерного, но алгоритмы, исправляющие этот недостаток, в изобилии есть в интернете. Да и сам алгоритм получения случайного числа можно изменить: например не считывать позицию курсора,
В общем, у меня вышел вот такой код:
#!/usr/local/bin/gsed -n -f
# Очищаем экран, выставляем цвет чёрное на чёрном, убираем курсор
1i\\x1B[2J\x1B[f\x1B[30;40m\x1B[?25l
# Читаем файл случайных чисел, пока не встретим перевод строки
1R /dev/urandom
# Запрашиваем текущие координаты курсора
1a\\x1B[6n
2{
# Смотрим чему равна первая (Y) координата, оставляем только её
s/.*\x1B\[\([0-9]*\);1R.*/Random number: \1/
# Убираем текущий текст в буфер
h
# Очищаем экран, восстанавливаем цвет и курсор
i\\x1B[2J\x1B[f\x1B[0m\x1B[?25h
# Вынимаем из буфера сохранённое
g
# Печатаем сохранённое на экран
p
# Выходим
q
}У него есть и недостаток — так как «Сед» всегда совершает действия только после того как получит данные снаружи, вам придётся дважды нажать «Энтер», чтобы получить ожидаемое. Но от этого уже никуда не денешься, разве что можно сократить количество нажатий до одного — если отказаться от считывания координат.
Оглядываясь на шахматы на sed (SedChess) ★
Это информационный пост, больше для себя. Для того, чтобы не забыть выводы и ощущения от сделанного.
Несколько месяцев назад я написал шахматы на утилите «сед», ненадолго заинтересовав публику. Особенно доставляли комментарии на «Реддите» — кажется, я поддержал имидж русских программистов, как людей для которых нет ничего невозможного.
Пара комментариев оттуда:


Заодно мои «шахматы» попали на «ЛОР», «ОупенНет» и многие другие ресурсы (например, в английской «Википедии» в статье про sed, появилась ссылка на меня).
Проект (если такое официальное слово вообще применимо к этой развлекухе) оказался полезен для меня лично: я глубже понял sed, потренировал мозг
Сохранился один лист из блокнота на котором я расписываю как движется

Ещё один плюс — мне много пришлось поупражняться в борьбе с собственной ленью и желанием бросить проект, когда я встречался с трудностями, которые казались непреодолимыми или заставляли переделывать половину проекта.
Конечно, мной двигали вовсе не рациональные побуждения, а желание сделать
Тяга делать
Как заменить табы, используя sed
Утилита командной строки sed (это потоковый редактор),
Я немного поэксперементировал, оказалось, что sed вполне воспринимает этот символ как таковой, а все «магические выражения» не работают. Поскольку «таб» имеет специальное значение в командной строке, ввести его можно либо через комбинацию Ctrl+V, tab, либо Ctrl+V, Ctrl+I. Во многих шеллах (например, в bash, ksh, sh) сработает специальный синтаксис с долларом, как в примере ниже.
Например, если вам надо заменить последовательные «табы» на один, то это может выглядеть вот так:
sed $'s/\t\t*/\t/g' sample.txt # именно \t\t*, а не \t+
# или
sed -E $'s/\t+/\t/g' sample.txt # в Линуксе ключ „-r“Если вы знаете как в sed можно работать с tab проще, расскажите, пожалуйста, в комментариях.