Есть ли способ печатать один и тот же символ повторно в bash, так же, как вы можете использовать эту конструкцию для этого в python:
print('%' * 3)
дает
%%%
Есть ли способ печатать один и тот же символ повторно в bash, так же, как вы можете использовать эту конструкцию для этого в python:
print('%' * 3)
дает
%%%
конечно, просто используйте printf
и немного bash манипуляции с строкой
$ s=$(printf "%-30s" "*")
$ echo "${s// /*}"
******************************
Должен быть более короткий путь, но в настоящее время, как я это сделаю. Вы можете сделать это функцией, которую вы можете сохранить в библиотеке для будущего использования.
printf_new() {
str=$1
num=$2
v=$(printf "%-${num}s" "$str")
echo "${v// /*}"
}
Тестирование:
$ printf_new "*" 20
********************
$ printf_new "*" 10
**********
$ printf_new "%" 10
%%%%%%%%%%
На самом деле это однострочный, который может сделать это:
printf "%0.s-" {1..10}
печатает
----------
Здесь пробой аргументов, переданных в printf
:
printf
обрезать строку, если она длиннее указанной длины, которая равна нулюprintf
, это может быть что угодно (для "%" вы должны избегать его с другим "%" сначала, то есть "%%" )printf
, если вы даете ему больше аргументов, чем указано в строке формата, нужно выполнить обратный возврат к началу строки формата и запустить его снова.Конечным результатом здесь является то, что вы сообщаете printf
, что вы хотите, чтобы он печатал строку нулевой длины без дополнительных символов, если предоставленная строка длиннее нуля. Затем после этой строки нулевой длины напечатайте символ "-" (или любой другой набор символов). Затем вы предоставляете ему 10 аргументов, поэтому он печатает 10 строк нулевой длины, каждый из которых имеет "-".
Это однострочный шрифт, который печатает любое количество повторяющихся символов!
Edit:
Кстати, если вы хотите напечатать символы $variable
, вам просто нужно немного изменить аргумент, чтобы использовать seq
, а не расширять фигуру следующим образом:
printf '%0.s-' $(seq 1 $variable)
Вместо этого передаются аргументы "1 2 3 4... $variable" до printf
, печатая точно $variable
экземпляры "-"
Текущий принятый ответ на этот вопрос (ghostdog74) предоставляет метод, который выполняется чрезвычайно медленно даже для умеренно большого количества символов. Ответ на верхний голос (CaffeineConnoisseur) лучше, но все еще довольно медленный.
Вот что в моих тестах выполнило быстрее всех (даже быстрее, чем версия python):
perl -E "print '*' x 1000"
На втором месте была команда python:
python -c "print('*' * 1000)"
Если ни perl, ни python не доступны, это будет третьим:
head -c 1000 /dev/zero | tr '\0' '*'
И на четвертом месте находится встроенный bash printf
с tr
:
printf '%*s' 1000 | tr ' ' '*'
И вот один (из CaffeineConnoisseur ответ), который на пятом месте в скорости для большого количества повторяющихся символов, но может быть быстрее для небольших чисел (из-за используя только встроенный bash, а не создавая внешний процесс):
printf '%.s*' {1..1000}
Мне это нравится:
echo $(yes % | head -n3)
Вам может не понравиться следующее:
for ((i=0; i<3; i++)){
echo -ne "%"
}
Вам может понравиться следующее:
s=$( printf "%3s" ); echo " ${s// /%}"
Источник: http://dbaspot.com/shell/357767-bash-fast-way-repeat-string.html
Существует также эта форма, но не очень полезная:
echo %{,,}
Это уродливо, но вы можете сделать это вот так:
$ for a in `seq 5`; do echo -n %; done
%%%%%
Конечно, seq
- внешняя программа (которую вы, вероятно, имеете).
Другой:
char='%'
count=5
result=$( printf "%${count}s" ' ' )
echo -e ${result// /$char}
Можно получить любое число нулевого символа (\0
) из /dev/zero
. Осталось только сделать это
head -c 20 /dev/zero |tr '\0' '+'
Обратите внимание, что head
и tr
являются внешними командами. Так что он будет вызываться в отдельном процессе.
"Оптимизировать" это решение можно с помощью кэширования строк.
CACHE="$(head -c 1000 /dev/zero |tr '\0' '+')"
echo "${CACHE:0:10}"
echo "${CACHE:0:100}"
echo "${CACHE:0:300}"
В выражении echo есть только bash
встроенные модули. Таким образом, мы можем использовать его в цикле.
#!/usr/bin/awk -f
BEGIN {
while (c++ < 3) printf "%"
}
Результат
%%%
Вот самый простой способ сделать это
seq -s % 4|tr -d '[:digit:]'
Обратите внимание, что в созданной последовательности будет только 3 '%'.