Хеллоу! Попался мне вчера чей-то очередной bash скрипт, в котором были такие конструкции:



echo '--------------' 

printf '%s\n' '--------------'



Так-то нормальная практика, но смотрится как-то уж очень не профессионально. У python и прочих языков такое можно реализовать примерно так:



python3 -c 'print("-" * 80)'

perl -E 'say "-" x 80'



А что-же с bash? Из коробки такой функции увы нет. Включаем «режим изобретателя». Поехали.



repeat(){

for i in {1..90}; do echo -n "$1"; done

}



repeat '-'



Создаём функцию с циклом repeat, в которую передадим символ «-» для повторения 90 раз. Вот оно! Уже намного лучше.



Теперь если мне нужно вывести какие-то заголовки в «рамке», я делаю так:



repeat '-';.

echo -e '\nHeader 1\t\tHeader 2\t\tHeader 3\t\t\t\tHeader 4';

repeat '-';



Уже не плохо. Символ \t означает = Табуляция. Ну а \n я думаю ты и так знаешь = Новая строка.



Гуд. Но функция все равно не универсальная, хочется большего. Давай теперь передадим в функцию repeat количество повторов. В предыдущем скрипте у меня зашит харкод на 90 символов. Вуаля:



repeat() {

range=$(seq $2)

for i in $range; do echo -n "$1"; done

}



repeat '-' 20



Передаем в функцию 2 параметра, первый = какой символ loop’ить, второй = сколько будет повторов. В примере выше, символ «-» выведется 20 раз.



Команда seq в этом скрипте выводит последовательность целых чисел с шагом, заданным пользователем. По-умолчанию, выводимые числа отделяются друг от друга символом перевода строки, однако, с помощью ключа -s может быть задан другой разделитель.



# seq 5

1

2

3

4

5



# seq -s : 5

1:2:3:4:5



С этим ок, разобрались. А что если воспользоваться printf? Давай попробуем.



С printf это реализуется намного проще, вот варианты:



printf -- '-%.0s' 1 2 3 4 5

printf -- '-%.0s' {1..20}



Разборка этой магии



Двойное тире означает «флаги командной строки». Поскольку мне нужно вывести «-», двойное тире указывает команде printf не пытаться анализировать то, что идет после параметров командной строки. 😶 ЧО?



Короче простым языком: если выводишь символ «-» через printf, то нужно двойное тире. Если выводишь к примеру символ «~» можно обойтись такой конструкцией:



printf '~%.0s' {1..20}; printf '\n'



Просто при выводе «-» printf думает что ты ему какой-то ключ хотел подсунуть и заорет: printf: -%: invalid option. В общем такая вот особенность. Ну либо всех обмануть и сделать так:



printf '%.0s-' {1..80}



Подобное можно реализовать с помощью внешних утилит таких как: awk/sed и т.п. Но чем больше ты усложняешь, тем тяжелее это дебажить. Это утверждение справедливо вообще для всего.



на закуску:

seq -s_ 20|tr -d '[:digit:]'



Надеюсь ты узнал что-то новое. Спасибо за внимание, ставь лайк, репости и приводи к нам своих коллег и друзей. Забашим!



tags: #bash



🟢 Подпишись: @bashdays