Здравствуйте, товарищи. Ну чо, как оно?

Поехали еBash’ить. Сегодня разберём интересную задачку, которую я подкидываю на собесы. Задача со звёздочкой.

Суть задачи: нужно вывести строки в окно терминала и пронумеровать их, используя только один вызов sed. Аналогично выводу команды nl.

То есть должно получиться такое:

printf '%s\n' {a..d} | nl
1 a
2 b
3 c
4 d

Только это нужно сделать с помощью одного вызова sed.

Обычно те, кто берётся её решать, спустя какое-то время говорят: «Роман, иди нахуй, это сделать невозможно!»

Так говорят бедолаги, которым либо лень что-то делать, либо писька ещё не отросла. Всё возможно, было бы желание.

Короче, поехали решать. Давай попробуем сразу с sed несколько вариантов.

printf '%s\n' {a..d} | sed '='
printf '%s\n' {a..d} | sed -n 'p;='
printf '%s\n' {a..d} | sed -n '=;p'

Ну чёт да… ожидаемый результат совсем не ожидаемый.

Дело в том, что, когда sed встречает команду «=», он тут же пишет текущий номер строки с завершающим символом «\n» или «\0». То есть номер и строка разделены «\n» или «\0».

Поэтому в примерах по sed для решения этой задачи используют два вызова.

printf '%s\n' {a..d} | sed '=' | sed 'N;s/\n/ /'

Вот так всё корректно отработает, но задачу мы не решили, условия другие. Нам можно использовать лишь один sed.

Чо будем делать? Думать, ёпта!

Для начала надо посмотреть, а что мы имеем и на что можем повлиять.

Утилита sed пишет строки. Куда она их пишет? Вот и решение…

Вставляем в начало каждой строки управляющую последовательность, которая переместит курсор на предыдущую строку и установит его, например, в 3-й колонке.

printf '%s\n' {a..d} | sed '=;s/^/\x1b[1A\x1b[3G/'

Получаем ожидаемый результат:

1 a
2 b
3 c
4 d

Поздравляю! Задача решена с помощью всего лишь одного вызова sed.

Роман Шубин
Роман Шубин
CEO & CTO, Главред в «Цифровой улей»
Задать вопрос
Если очевидные решения не приносят результата, всегда можно воспользоваться неочевидными. Благо таких неочевидных решений бесконечное множество.

Изучай. Всех с пятницей и хороших предстоящих выходных. Береги себя!