Как я могу повторить символ в Bash?

Как я мог сделать это с echo?

perl -E 'say "=" x 100'

person sid_com    schedule 18.03.2011    source источник
comment
К сожалению, это не Баш.   -  person solidsnack    schedule 20.02.2016
comment
не с эхом, а по той же теме ruby -e 'puts "=" * 100' или python -c 'print "=" * 100'   -  person Evgeny    schedule 20.04.2017
comment
Отличный вопрос. Очень хорошие ответы. Я использовал здесь один из ответов в реальной работе, который я опубликую в качестве примера: github.com/drbeco/oldfiles/blob/master/oldfiles (используется printf с seq) svrb=`printf '%.sv' $(seq $vrb)`   -  person DrBeco    schedule 07.07.2017
comment
Общее решение для печати чего угодно (1 или более символов, включая символы новой строки): Repeat_this () {i = 1; в то время как [$ i -le $ 2]; сделать printf% s $ 1; я = $ (($ я + 1)); Выполнено ; printf '\ n';}. Используйте так: Повторить это что-то Число_повторов. Например, чтобы продемонстрировать 5-кратное повторение чего-то, включая 3 символа новой строки: Repeat_this $ (printf '\ n \ n \ nthis') 5. Последний printf '\ n' может быть удален (но я вставляю его для создания текстовых файлов, а им нужна новая строка в качестве последнего символа!)   -  person Olivier Dulac    schedule 14.02.2020


Ответы (32)


Ты можешь использовать:

printf '=%.0s' {1..100}

Как это работает:

Bash расширяет {1..100}, поэтому команда принимает следующий вид:

printf '=%.0s' 1 2 3 4 ... 100

Я установил для printf формат =%.0s, что означает, что он всегда будет печатать один =, независимо от того, какой аргумент ему дан. Следовательно, он печатает 100 =сек.

person dogbane    schedule 18.03.2011
comment
Отличное решение, которое достаточно хорошо работает даже при большом количестве повторов. Вот оболочка функции, которую вы можете вызвать, например, с repl = 100 (eval, к сожалению, требуется хитрость, чтобы основать расширение фигурных скобок на переменной): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); } - person mklement0; 08.12.2013
comment
Можно ли установить верхний предел с помощью var? Я пробовал и не могу заставить его работать. - person Mike Purcell; 11.01.2014
comment
Вы не можете использовать переменные в скобках. Вместо этого используйте seq, например. $(seq 1 $limit). - person dogbane; 11.01.2014
comment
Вот еще одна функция, которая использует слово в качестве аргумента и печатает в зависимости от количества символов в слове: repl () { printf '=%.0s' $(seq 2 $(echo $1 | wc -c)); } Использование: repl 'Installing something' или repl "Installing $package" - person reubano; 01.05.2014
comment
Вы можете использовать переменные с расширением скобок в ksh и zsh, к сожалению, это просто bash, который расширяет вещи в другом и глупом порядке. - person Adrian Frühwirth; 02.05.2014
comment
Если вы введете его в действие, лучше всего переставить его с $s%.0s на %.0s$s, иначе дефисы вызовут printf ошибку. - person KomodoDave; 30.07.2014
comment
@dogbane n=5; eval "echo {1..$n}" Но seq более элегантен. - person Palec; 16.11.2014
comment
Это заставило меня заметить поведение printf в Bash: он продолжает применять строку формата до тех пор, пока не останутся аргументы. Я предполагал, что он обработал строку формата только один раз! - person Jeenu; 08.01.2015
comment
Если вы хотите указать ширину с помощью переменной w, как насчет printf "%${w}s" '' | tr ' ' =? - person IpsRich; 24.07.2015
comment
Вы также можете использовать: len=20; eval "printf "%0.s$c" {1..$len}" - person rowan; 08.03.2017
comment
он также работает без нуля после точки: echo "$(printf '=%.s' {1..100})" - person Alex; 12.06.2017
comment
+1 в ответ, но я по-прежнему использовал Equals="=============" и Dashes="------------", определенные в глобальном разделе bash, а затем ссылались на циклы печати в локальных функциях bash для повышения производительности и удобочитаемости. Сегодня чувствую себя виноватым, но я знаю, что буду признателен за систему KISS через 5 лет. - person WinEunuuchs2Unix; 25.06.2017
comment
Если вы пытаетесь повторить дефис -, вы можете поместить его в конец строки формата '%.0s-', иначе вы получите сообщение об ошибке, потому что начальный дефис будет интерпретирован как опция. - person wisbucky; 09.12.2017
comment
Чтобы добавить новую строку, вы можете: echo $ (printf '=%. 0s' {1..100}) - person AmanicA; 07.06.2018
comment
printf '=%.0s' выходы =. Так что не вариант, когда нужно произвольное количество =. А если быть точным, произвольное количество пробелов для отступа. Решение other отлично подходит для этого случая. А именно printf "%${n}s" | tr ' ' '=' - person x-yuri; 18.09.2018
comment
что означает .0 в этом ответе? И это регулярное выражение или printf - person KPCT; 16.03.2019
comment
@ 0x476f72616e From man 3 printf: Необязательная точность в виде точки ('.'), За которой следует необязательная строка десятичных цифр. [..] Если точность указана как ".", Точность принимается равной нулю. [..] максимальное количество символов, которое будет напечатано из строки для преобразований s и S. Поэтому я ожидал, что он будет работать и без 0. - person Jonathan Komar; 21.09.2020
comment
Если вы сделаете это в vim, вам нужно будет экранировать %. Попробуйте добавить строку комментария в LaTeX: read !printf '\%\%\%.s' {1..50} - person Jonathan Komar; 21.09.2020
comment
printf '-%.0s' {1..100} не работает - person Angel; 24.02.2021

Непростой путь. Но например:

seq -s= 100|tr -d '[:digit:]'

Или, может быть, способ, соответствующий стандарту:

printf %100s |tr " " "="

Еще есть tput rep, но что касается моих терминалов (xterm и linux), похоже, они его не поддерживают :)

person Community    schedule 18.03.2011
comment
Обратите внимание, что первая опция с seq печатает на единицу меньше указанного числа, поэтому в этом примере будет напечатано 99 = символов. - person Camilo Martin; 02.01.2014
comment
printf tr - единственное решение POSIX, потому что seq, yes и {1..3} не являются POSIX. - person Ciro Santilli 新疆再教育营六四事件ۍ 10.04.2014
comment
Чтобы повторить строку, а не только один символ: printf %100s | sed 's/ /abc/g' - выводит 'abcabcabc ...' - person John Rix; 11.09.2014
comment
+1 за отсутствие циклов и только одну внешнюю команду (tr). Вы также можете расширить его до чего-то вроде printf "%${COLUMNS}s\n" | tr " " "=". - person musiphil; 16.03.2015
comment
@CamiloMartin: Я этого не вижу; и GNU, и BSD seq, похоже, возвращают ожидаемые 100 символов. когда я бегу seq -s= 100 | tr -d '[:digit:]' | wc -m. Если у вас это действительно не работает: какую seq реализацию вы используете? - person mklement0; 29.04.2015
comment
@ mklement0 В Ubuntu 14.04.2 LTS, которая поставляется с GNU seq 8.21, я получаю на единицу меньше указанного числа; см. снимок экрана. Теперь я спрашиваю, на какой платформе вы находитесь, потому что я думал, что это последовательно. Вот снимок экрана с RaspberryPi и даже в Windows. - person Camilo Martin; 03.05.2015
comment
@CamiloMartin: Спасибо за продолжение: это действительно сводится к реализации seq (и, следовательно, неявно к платформе): GNU seq (Linux) производит на 1 меньше =, чем указанное число (в отличие от того, что я первоначально утверждал, но как вы правильно определили), тогда как BSD seq (BSD-подобные платформы, включая OSX) выдает желаемое число. Простая тестовая команда: seq -s= 100 | tr -d '[:digit:]\n' | wc -c BSD seq помещает = после каждого числа, включая последнее, тогда как GNU seq помещает новую строку после последнего число, таким образом, сокращается на 1 по отношению к счетчику =. - person mklement0; 03.05.2015
comment
@ mklement0 Ну, я надеялся, что вы по ошибке подсчитали последний символ новой строки с wc. Единственный вывод, который я могу сделать из этого: seq не следует использовать. - person Camilo Martin; 03.05.2015
comment
@CamiloMartin: Согласен: printf решение является портативным, и его проще загружать. - person mklement0; 04.05.2015
comment
Я не смог заставить tput rep работать, но прямая последовательность ANSI работает. Я думаю, что tput не может правильно обработать termcap синтаксис rep=%p1%c\E[%p2%{1}%-%db или в Termcap терминала Gnome отсутствует запись. См. Мой ответ: stackoverflow.com/a/59251780/7939871 - person Léa Gris; 10.12.2019
comment
У меня стандартное использование printf отлично работало под оболочкой POSIX. Большое спасибо. - person Bob Jarvis - Reinstate Monica; 02.10.2020

Совет от @ gniourf_gniourf за его вклад.

Примечание. Этот ответ не отвечает на исходный вопрос, но дополняет существующие полезные ответы, сравнивая эффективность.

Решения сравниваются только по скорости выполнения - требования к памяти не учитываются (они различаются в зависимости от решения и могут иметь значение при большом количестве повторов).

Резюме:

  • If your repeat count is small, say up to around 100, it's worth going with the Bash-only solutions, as the startup cost of external utilities matters, especially Perl's.
    • Pragmatically speaking, however, if you only need one instance of repeating characters, all existing solutions may be fine.
  • With large repeat counts, use external utilities, as they'll be much faster.
    • In particular, avoid Bash's global substring replacement with large strings
      (e.g., ${var// /=}), as it is prohibitively slow.

Ниже приведены тайминги, снятые на iMac конца 2012 года с процессором Intel Core i5 3,2 ГГц и накопителем Fusion Drive, работающим под OSX 10.10.4 и bash 3.2.57, и это в среднем 1000 запусков.

Записи:

  • перечислены в порядке возрастания продолжительности выполнения (сначала самый быстрый)
  • prefixed with:
    • M ... a potentially multi-character solution
    • S ... одно -символьное решение
    • P ... решение, совместимое с POSIX
  • с последующим кратким описанием решения
  • с суффиксом имени автора исходного ответа

  • Малое количество повторов: 100
[M, P] printf %.s= [dogbane]:                           0.0002
[M   ] printf + bash global substr. replacement [Tim]:  0.0005
[M   ] echo -n - brace expansion loop [eugene y]:       0.0007
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         0.0013
[M   ] seq -f [Sam Salisbury]:                          0.0016
[M   ] jot -b [Stefan Ludwig]:                          0.0016
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.0019
[M, P] awk - while loop [Steven Penny]:                 0.0019
[S   ] printf + tr [user332325]:                        0.0021
[S   ] head + tr [eugene y]:                            0.0021
[S, P] dd + tr [mklement0]:                             0.0021
[M   ] printf + sed [user332325 (comment)]:             0.0021
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0025
[M, P] mawk - while loop [Steven Penny]:                0.0026
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0028
[M, P] gawk - while loop [Steven Penny]:                0.0028
[M   ] yes + head + tr [Digital Trauma]:                0.0029
[M   ] Perl [sid_com]:                                  0.0059
  • Решения, предназначенные только для Bash, возглавляют список - но только с таким маленьким количеством повторений! (увидеть ниже).
  • Здесь имеет значение стоимость запуска внешних утилит, особенно Perl. Если вы должны вызывать это в цикле - с малым счетчиком повторений на каждой итерации - избегайте многоцелевых решений, awk и perl.

  • Большое количество повторов: 1000000 (1 миллион)
[M   ] Perl [sid_com]:                                  0.0067
[M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0254
[M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0599
[S   ] head + tr [eugene y]:                            0.1143
[S, P] dd + tr [mklement0]:                             0.1144
[S   ] printf + tr [user332325]:                        0.1164
[M, P] mawk - while loop [Steven Penny]:                0.1434
[M   ] seq -f [Sam Salisbury]:                          0.1452
[M   ] jot -b [Stefan Ludwig]:                          0.1690
[M   ] printf + sed [user332325 (comment)]:             0.1735
[M   ] yes + head + tr [Digital Trauma]:                0.1883
[M, P] gawk - while loop [Steven Penny]:                0.2493
[M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.2614
[M, P] awk - while loop [Steven Penny]:                 0.3211
[M, P] printf %.s= [dogbane]:                           2.4565
[M   ] echo -n - brace expansion loop [eugene y]:       7.5877
[M   ] echo -n - arithmetic loop [Eliah Kagan]:         13.5426
[M   ] printf + bash global substr. replacement [Tim]:  n/a
  • Решение Perl из этого вопроса на сегодняшний день является самым быстрым.
  • Глобальная замена строк в Bash (${foo// /=}) необъяснимо мучительно медленна с большими строками и была исключена из работы (заняло около 50 минут (!) В Bash 4.3.30 и даже дольше в Bash 3.2.57 - я никогда не ждал для его завершения).
  • Циклы Bash медленные, а арифметические циклы ((( i= 0; ... ))) медленнее, чем циклы с расширением скобок ({1..n}), хотя арифметические циклы более эффективны с точки зрения памяти.
  • awk относится к BSD awk (как и в OSX) - он заметно медленнее, чем gawk (GNU Awk) и особенно mawk.
  • Обратите внимание, что с большим количеством символов и несколькими символами. строк, потребление памяти может стать предметом рассмотрения - подходы в этом отношении различаются.

Вот сценарий Bash (testrepeat), который произвел это. Требуется 2 аргумента:

  • количество повторений символов
  • необязательно, количество выполняемых тестовых прогонов и для расчета среднего времени от

Другими словами: время, указанное выше, было получено с testrepeat 100 1000 и testrepeat 1000000 1000

#!/usr/bin/env bash

title() { printf '%s:\t' "$1"; }

TIMEFORMAT=$'%6Rs'

# The number of repetitions of the input chars. to produce
COUNT_REPETITIONS=${1?Arguments: <charRepeatCount> [<testRunCount>]}

# The number of test runs to perform to derive the average timing from.
COUNT_RUNS=${2:-1}

# Discard the (stdout) output generated by default.
# If you want to check the results, replace '/dev/null' on the following
# line with a prefix path to which a running index starting with 1 will
# be appended for each test run; e.g., outFilePrefix='outfile', which
# will produce outfile1, outfile2, ...
outFilePrefix=/dev/null

{

  outFile=$outFilePrefix
  ndx=0

  title '[M, P] printf %.s= [dogbane]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf '%.s=' {1..$COUNT_REPETITIONS} >"$outFile"
  done"

  title '[M   ] echo -n - arithmetic loop [Eliah Kagan]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for ((i=0; i<COUNT_REPETITIONS; ++i)); do echo -n =; done >"$outFile"
  done


  title '[M   ] echo -n - brace expansion loop [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In order to use brace expansion with a variable, we must use `eval`.
  eval "
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    for i in {1..$COUNT_REPETITIONS}; do echo -n =; done >"$outFile"
  done
  "

  title '[M   ] printf + sed [user332325 (comment)]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | sed 's/ /=/g' >"$outFile"
  done


  title '[S   ] printf + tr [user332325]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    printf "%${COUNT_REPETITIONS}s" | tr ' ' '='  >"$outFile"
  done


  title '[S   ] head + tr [eugene y]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    head -c $COUNT_REPETITIONS < /dev/zero | tr '\0' '=' >"$outFile"
  done


  title '[M   ] seq -f [Sam Salisbury]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    seq -f '=' -s '' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] jot -b [Stefan Ludwig]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    jot -s '' -b '=' $COUNT_REPETITIONS >"$outFile"
  done


  title '[M   ] yes + head + tr [Digital Trauma]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    yes = | head -$COUNT_REPETITIONS | tr -d '\n'  >"$outFile"
  done

  title '[M   ] Perl [sid_com]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    perl -e "print \"=\" x $COUNT_REPETITIONS" >"$outFile"
  done

  title '[S, P] dd + tr [mklement0]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  time for (( n = 0; n < COUNT_RUNS; n++ )); do 
    dd if=/dev/zero bs=$COUNT_REPETITIONS count=1 2>/dev/null | tr '\0' "=" >"$outFile"
  done

  # !! On OSX, awk is BSD awk, and mawk and gawk were installed later.
  # !! On Linux systems, awk may refer to either mawk or gawk.
  for awkBin in awk mawk gawk; do
    if [[ -x $(command -v $awkBin) ]]; then

      title "[M   ] $awkBin"' - $(count+1)="=" [Steven Penny (variant)]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { OFS="="; $(count+1)=""; print }' >"$outFile"
      done

      title "[M, P] $awkBin"' - while loop [Steven Penny]'
      [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
      time for (( n = 0; n < COUNT_RUNS; n++ )); do 
        $awkBin -v count=$COUNT_REPETITIONS 'BEGIN { while (i++ < count) printf "=" }' >"$outFile"
      done

    fi
  done

  title '[M   ] printf + bash global substr. replacement [Tim]'
  [[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
  # !! In Bash 4.3.30 a single run with repeat count of 1 million took almost
  # !! 50 *minutes*(!) to complete; n Bash 3.2.57 it's seemingly even slower -
  # !! didn't wait for it to finish.
  # !! Thus, this test is skipped for counts that are likely to be much slower
  # !! than the other tests.
  skip=0
  [[ $BASH_VERSINFO -le 3 && COUNT_REPETITIONS -gt 1000 ]] && skip=1
  [[ $BASH_VERSINFO -eq 4 && COUNT_REPETITIONS -gt 10000 ]] && skip=1
  if (( skip )); then
    echo 'n/a' >&2
  else
    time for (( n = 0; n < COUNT_RUNS; n++ )); do 
      { printf -v t "%${COUNT_REPETITIONS}s" '='; printf %s "${t// /=}"; } >"$outFile"
    done
  fi
} 2>&1 | 
 sort -t$'\t' -k2,2n | 
   awk -F $'\t' -v count=$COUNT_RUNS '{ 
    printf "%s\t", $1; 
    if ($2 ~ "^n/a") { print $2 } else { printf "%.4f\n", $2 / count }}' |
     column -s$'\t' -t
person mklement0    schedule 17.05.2015
comment
Интересно посмотреть на сравнение таймингов, но я думаю, что во многих программах вывод буферизуется, поэтому их тайминги можно изменить, если буферизация была отключена. - person Sergiy Kolodyazhnyy; 19.01.2017
comment
Таким образом, решение perl (sid_com) в основном является самым быстрым ... после того, как будут достигнуты начальные накладные расходы на запуск perl. (от 59 мс для небольшого повтора до 67 мс для миллиона повторов ... поэтому разветвление perl заняло примерно 59 мс в вашей системе) - person Olivier Dulac; 13.02.2020

Есть несколько способов сделать это.

Использование петли:

  • Раскладку скобок можно использовать с целочисленными литералами:

    for i in {1..100}; do echo -n =; done    
    
  • Цикл в стиле C позволяет использовать переменные:

    start=1
    end=100
    for ((i=$start; i<=$end; i++)); do echo -n =; done
    

Использование встроенной функции printf:

printf '=%.0s' {1..100}

При указании точности строка обрезается до указанной ширины (0). Поскольку printf повторно использует строку формата для использования всех аргументов, она просто печатает "=" 100 раз.

Использование head (printf и т. д.) и tr:

head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="
person Eugene Yarmash    schedule 18.03.2011
comment
++ для решения head / tr, которое хорошо работает даже при большом количестве повторов (небольшое предостережение: head -c не соответствует стандарту POSIX, но его реализуют как BSD, так и GNU head); в то время как два других решения в этом случае будут медленными, у них есть преимущество работы с многосимвольными строками. - person mklement0; 29.04.2015
comment
Использование yes и head - полезно, если вам нужно определенное количество символов новой строки: yes "" | head -n 100. tr может заставить его печатать любой символ: yes "" | head -n 100 | tr "\n" "="; echo - person loxaxs; 27.05.2018
comment
Несколько удивительно: dd if=/dev/zero count=1 bs=100000000 | tr '\0' '=' >/dev/null значительно медленнее, чем версия head -c100000000 < /dev/zero | tr '\0' '=' >/dev/null. Конечно, вы должны использовать размер блока 100M +, чтобы разумно измерить разницу во времени. 100 Мбайт занимает 1,7 с и 1 с для двух соответствующих версий. Я снял tr и просто сбросил его в /dev/null и получил 0,287 с для версии head и 0,675 с для версии dd для миллиарда байт. - person Michael Goldshteyn; 11.08.2018
comment
Для: dd if=/dev/zero count=1 bs=100000000 | tr '\0' '=' >/dev/null = ›0,21332 s, 469 MB/s; Для: dd if=/dev/zero count=100 bs=1000000| tr '\0' '=' >/dev/null = ›0,161579 s, 619 MB/s; - person 3ED; 18.08.2018
comment
printf '-%.0s' {1..100} не работает - person Angel; 24.02.2021

Я только что нашел очень простой способ сделать это с помощью seq:

ОБНОВЛЕНИЕ: работает на BSD seq, которая поставляется с OS X. YMMV с другими версиями

seq  -f "#" -s '' 10

Напечатает '#' 10 раз, вот так:

##########
  • -f "#" устанавливает строку формата, чтобы игнорировать числа и просто печатать # для каждого из них.
  • -s '' устанавливает разделитель на пустую строку, чтобы удалить символы новой строки, которые seq вставляет между каждым числом
  • Пробелы после -f и -s кажутся важными.

РЕДАКТИРОВАТЬ: Вот это удобная функция ...

repeat () {
    seq  -f $1 -s '' $2; echo
}

Что вы можете назвать так ...

repeat "#" 10

ПРИМЕЧАНИЕ. Если вы повторяете #, цитаты важны!

person Sam Salisbury    schedule 02.05.2014
comment
Это дает мне seq: format ‘#’ has no % directive. seq предназначен для чисел, а не для строк. См. gnu.org/software/coreutils/manual/html_node/seq -invocation.html - person John B; 07.07.2014
comment
Ах, значит, я использовал версию seq для BSD, найденную в OS X. Я обновлю ответ. Какую версию вы используете? - person Sam Salisbury; 08.07.2014
comment
Я использую seq из GNU coreutils. - person John B; 08.07.2014
comment
@JohnB: BSD seq здесь ловко перепрофилируется для репликации строк: строка формата, переданная в -f - обычно используется для форматирования генерируемых чисел - содержит только строку для репликации здесь, так что вывод содержит только копии этой строки. К сожалению, GNU seq настаивает на наличии числового формата в строке формата, и это ошибка, которую вы видите. - person mklement0; 29.04.2015
comment
Красиво сделано; также работает со строками с несколькими символами. Используйте "$1" (двойные кавычки), чтобы вы также могли передавать символы, такие как '*', и строки со встроенными пробелами. Наконец, если вы хотите использовать %, вы должны удвоить его (иначе seq будет думать, что это часть спецификации формата, такой как %f); использование "${1//%/%%}" позаботится об этом. Поскольку (как вы упомянули) вы используете BSD seq, этот будет работать с BSD-подобными ОС в целом (например, FreeBSD) - напротив, он не будет работать в Linux, где используется GNU seq. - person mklement0; 29.04.2015
comment
Между -f и "#" пробел не необходим, потому что аргумент-параметр непустой. Он является обязательным после -s, потому что технически невозможно передать пустую строку в качестве аргумента-параметра, непосредственно присоединяя ее к -s: оболочке удаляет кавычки из строки -s'' перед передачей в seq, поэтому seq будет видеть только -s. # - не единственный символ, который нужно заключать в кавычки - также можно использовать так называемые метасимволы оболочки и *; лучше просто всегда цитировать. - person mklement0; 29.04.2015
comment
Это, похоже, не работает с символами Unicode (в моем случае символы рисования ящиков). BD_H="\xE2\x94\x80"; repeat "${BD_H}" 20 отображает 20 пробелов. - person Andris; 27.04.2017

Вот два интересных способа:

ubuntu@ubuntu:~$ yes = | head -10 | paste -s -d '' -
==========
ubuntu@ubuntu:~$ yes = | head -10 | tr -d "\n"
==========ubuntu@ubuntu:~$ 

Обратите внимание, что эти два элемента немного отличаются - метод paste заканчивается новой строкой. Метод tr - нет.

person Digital Trauma    schedule 21.11.2013
comment
Красиво сделано; обратите внимание, что BSD paste необъяснимо требует -d '\0' для указания пустого разделителя и не работает с -d '' - -d '\0' должен работать со всеми POSIX-совместимыми реализациями paste и действительно также работает с GNU paste . - person mklement0; 29.04.2015
comment
Похожий по духу, с меньшим количеством подвесных инструментов: yes | mapfile -n 100 -C 'printf = \#' -c 1 - person bishop; 27.04.2016
comment
@bishop: Хотя ваша команда действительно создает на одну подоболочку меньше, она все же медленнее для большего количества повторов, а для меньшего количества повторов разница, вероятно, не имеет значения; точный порог, вероятно, зависит как от оборудования, так и от ОС, например, на моем компьютере с OSX 10.11.5 этот ответ уже быстрее на 500; попробуйте time yes = | head -500 | paste -s -d '\0' -; time yes | mapfile -n 500 -C 'printf = \#' -c 1. Но что еще более важно: если вы все равно используете printf, вы можете использовать как более простой, так и более эффективный подход из принятого ответа: printf '%.s=' $(seq 500) - person mklement0; 17.07.2016

Нет простого пути. Избегайте циклов с использованием printf и подстановки.

str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
person Tim    schedule 18.03.2011
comment
Неплохо, но разумно работает только при небольшом количестве повторов. Вот оболочка функции, которую можно вызвать, например, как repl = 100 (не выводит завершающий \n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; } - person mklement0; 07.12.2013
comment
@ mklement0 Приятно, что вы предоставили функциональные версии обоих решений, +1 для обоих! - person Camilo Martin; 02.01.2014
comment
Отличное решение, не требующее внешних программ. Однако я бы использовал printf -v str … вместо str=$(printf …), чтобы не вызывать подоболочку. И для общего решения я бы использовал printf "%s" "${str// /rep}" вместо echo, потому что printf более надежен и не подавляется строками, начинающимися с -, как это делает echo. - person musiphil; 08.05.2021

Вопрос был в том, как это сделать с echo:

echo -e ''$_{1..100}'\b='

Это будет делать то же самое, что и perl -E 'say "=" x 100', но только с echo.

person manifestor    schedule 05.01.2019
comment
Это необычно, если вы не добавляете в него лишние пробелы-пробелы ... или очищаете его, используя: echo -e $ _ {1..100} '\ b =' | столб - person anthony; 20.08.2019
comment
Плохая идея. Это не удастся, если $_1, $_2 или любая другая из сотни переменных имеют значения. - person John Kugelman; 09.11.2019
comment
@JohnKugelman echo $ (set -; eval echo -e \ $ {{1..100}} '\\ b =') - person mug896; 29.02.2020
comment
Это брутто. Я люблю это: D - person dimo414; 26.05.2020

Если вам нужна совместимость с POSIX и согласованность между различными реализациями echo и printf и / или оболочками, отличными от просто bash:

seq(){ n=$1; while [ $n -le $2 ]; do echo $n; n=$((n+1)); done ;} # If you don't have it.

echo $(for each in $(seq 1 100); do printf "="; done)

... почти везде будет выводить тот же результат, что и perl -E 'say "=" x 100'.

person Geoff Nixon    schedule 07.12.2014
comment
Проблема в том, что seq не является утилитой POSIX (хотя системы BSD и Linux имеют ее реализации) - вместо этого вы можете выполнять арифметику оболочки POSIX с помощью цикла while, как в ответе @ Xennex81 (с printf "=", как вы правильно предлагаете, а не echo -n). - person mklement0; 29.04.2015
comment
Ой, вы совершенно правы. Подобные вещи иногда просто ускользают от меня, потому что этот стандарт не имеет никакого смысла. cal - это POSIX. seq нет. В любом случае, вместо того, чтобы переписывать ответ с помощью цикла while (как вы говорите, это уже есть в других ответах), я добавлю функцию RYO. Это более познавательно ;-). - person Geoff Nixon; 03.05.2015

Чистый способ Bash без eval, без подоболочки, без внешних инструментов, без расширений скобок (то есть вы можете иметь число, которое будет повторяться в переменной):

Если вам дана переменная n, которая расширяется до (неотрицательного) числа, и переменная pattern, например,

$ n=5
$ pattern=hello
$ printf -v output '%*s' "$n"
$ output=${output// /$pattern}
$ echo "$output"
hellohellohellohellohello

Вы можете создать функцию с помощью этого:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    local tmp
    printf -v tmp '%*s' "$1"
    printf -v "$3" '%s' "${tmp// /$2}"
}

С этим набором:

$ repeat 5 hello output
$ echo "$output"
hellohellohellohellohello

Для этого небольшого трюка мы довольно часто используем printf:

  • -v varname: вместо вывода на стандартный вывод printf поместит содержимое форматированной строки в переменную varname.
  • '% * s': printf будет использовать аргумент для печати соответствующего количества пробелов. Например, printf '%*s' 42 напечатает 42 пробела.
  • Наконец, когда у нас есть желаемое количество пробелов в нашей переменной, мы используем расширение параметра, чтобы заменить все пробелы нашим шаблоном: ${var// /$pattern} будет расширяться до расширения var со всеми пробелами, замененными расширением $pattern.

Вы также можете избавиться от переменной tmp в функции repeat, используя косвенное расширение:

repeat() {
    # $1=number of patterns to repeat
    # $2=pattern
    # $3=output variable name
    printf -v "$3" '%*s' "$1"
    printf -v "$3" '%s' "${!3// /$2}"
}
person gniourf_gniourf    schedule 01.06.2014
comment
Интересный вариант для передачи имени переменной. Хотя это решение подходит для повторных подсчетов примерно до 1000 (и, следовательно, вероятно, подходит для большинства реальных приложений, если я предполагаю), оно становится очень медленным для более высоких подсчетов (см. Следующий комментарий). - person mklement0; 29.04.2015
comment
Кажется, что глобальные операции замены строк bash в контексте расширения параметров (${var//old/new}) особенно медленны: мучительно медленные в bash 3.2.57 и медленные в bash 4.3.30, по крайней мере, в моей системе OSX 10.10.3 на машине Intel Core i5 с тактовой частотой 3,2 ГГц : При счете 1000 все идет медленно (3.2.57) / быстро (4.3.30): 0,1 / 0,004 секунды. Увеличение числа до 10 000 дает совершенно разные числа: repeat 10000 = var занимает около 80 секунд (!) В bash 3.2.57 и около 0,3 секунды в bash 4.3.30 (намного быстрее, чем в 3.2.57, но все же медленно). - person mklement0; 29.04.2015

Вот что я использую для печати строки символов на экране в Linux (в зависимости от ширины терминала / экрана)

Печать = по экрану:

printf '=%.0s' $(seq 1 $(tput cols))

Пояснение:

Выведите знак равенства столько раз, сколько заданная последовательность:

printf '=%.0s' #sequence

Используйте вывод команды (это функция bash, называемая подстановкой команд):

$(example_command)

Приведите последовательность, я использовал в качестве примера от 1 до 20. В последней команде вместо 20 используется команда tput:

seq 1 20

Укажите количество столбцов, которые в настоящее время используются в терминале:

tput cols
person mattbell87    schedule 06.02.2020
comment
printf '-%.0s' {1..100} не работает - person Angel; 24.02.2021

#!/usr/bin/awk -f
BEGIN {
  OFS = "="
  NF = 100
  print
}

Or

#!/usr/bin/awk -f
BEGIN {
  while (z++ < 100) printf "="
}

Пример

person Steven Penny    schedule 01.06.2014
comment
Красиво сделано; это соответствует стандарту POSIX и достаточно быстро даже при большом количестве повторов, а также поддерживает многосимвольные строки. Вот версия оболочки: awk 'BEGIN { while (c++ < 100) printf "=" }'. Обернутая в параметризованную функцию оболочки (например, вызывается как repeat 100 =): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (Пустой префикс . char и дополнительный вызов substr необходимы для обхода ошибки в BSD awk, где передача значения переменной, которая начинается с =, прерывает команду.) - person mklement0; 29.04.2015
comment
Решение NF = 100 очень умное (хотя чтобы получить 100 =, вы должны использовать NF = 101). Предостережения заключаются в том, что он приводит к сбою BSD awk (но это очень быстро с gawk и даже быстрее с mawk), и что POSIX не обсуждает ни присвоение NF, ни использование полей в BEGIN блоках. Вы можете заставить его работать и в BSD awk с небольшой настройкой: awk 'BEGIN { OFS = "="; $101=""; print }' (но, что любопытно, в BSD awk это не быстрее, чем решение цикла). В качестве параметризованного решения оболочки: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }. - person mklement0; 14.05.2015
comment
Примечание для пользователей. Уловка NF = 100 вызывает ошибку сегмента на более старой версии awk. original-awk - это имя под Linux более старой awk, похожей на BSD awk, которая, как сообщалось, вылетала из строя, если вы хотите попробовать это. Обратите внимание, что сбой обычно является первым шагом к обнаружению уязвимой ошибки. Этот ответ настолько продвигает небезопасный код. - person ; 25.08.2015
comment
Примечание для пользователей - original-awk нестандартно и не рекомендуется - person Steven Penny; 26.08.2015
comment
Альтернативой первому фрагменту кода может быть awk NF=100 OFS='=' <<< "" (с использованием bash и gawk) - person oliv; 24.05.2018
comment
@ user2350426: Я считаю, что это происходит из-за того, что исходный awk был ограничен 99 полями в строке (.. и это во многих случаях раздражает :() - person Olivier Dulac; 14.02.2020

Еще один способ повторить произвольную строку n раз:

Плюсы:

  • Работает с оболочкой POSIX.
  • Выход может быть назначен переменной.
  • Повторяет любую строку.
  • Очень быстро даже с очень большими повторами.

Минусы:

  • Требуется команда yes Gnu Core Utils.
#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"

С терминалом ANSI и повторением символов US-ASCII. Вы можете использовать escape-последовательность ANSI CSI. Это самый быстрый способ повторить символ.

#!/usr/bin/env bash

char='='
repeat_count=80
printf '%c\e[%db' "$char" "$repeat_count"

Или статически:

Выведите строку 80 раз =:

printf '=\e[80b\n'

Ограничения:

  • Не все терминалы понимают последовательность repeat_char ANSI CSI.
  • Могут повторяться только символы US-ASCII или однобайтовые символы ISO.
  • Повторение останавливается в последнем столбце, поэтому вы можете использовать большое значение для заполнения всей строки независимо от ширины терминала.
  • Повтор только для отображения. При захвате вывода в переменную оболочки последовательность repeat_char ANSI CSI не преобразуется в повторяющийся символ.
person Léa Gris    schedule 09.12.2019
comment
Незначительное примечание - REP (CSI b) должен нормально выполняться, если терминал находится в режиме переноса. - person jerch; 03.01.2020

В bash 3.0 или выше

for i in {1..100};do echo -n =;done
person loafoe    schedule 18.03.2011

Я предполагаю, что первоначальная цель вопроса заключалась в том, чтобы сделать это только с помощью встроенных команд оболочки. Таким образом, for циклы и printf будут допустимы, а rep, perl, а также jot ниже - нет. Тем не менее, следующая команда

jot -s "/" -b "\\" $((COLUMNS/2))

например, печатает строку \/\/\/\/\/\/\/\/\/\/\/\/ во всю ширину окна

person Stefan Ludwig    schedule 21.11.2013
comment
Красиво сделано; это хорошо работает даже при большом количестве повторов (при одновременной поддержке многосимвольных строк). Чтобы лучше проиллюстрировать подход, вот эквивалент команды OP: jot -s '' -b '=' 100. Предостережение заключается в том, что, хотя платформы, подобные BSD, включая OSX, поставляются с jot, дистрибутивы Linux не имеют. - person mklement0; 29.04.2015
comment
Спасибо, мне даже больше нравится, что вы используете -s ''. Я изменил свои сценарии. - person Stefan Ludwig; 30.04.2015
comment
В последних системах на основе Debian apt install athena-jot предоставит jot. - person agc; 08.02.2019

Как уже говорили другие, в bash расширение фигурных скобок предшествует расширение параметра, поэтому {m,n} диапазоны могут содержать только литералы. seq и _ 3_ предоставляют чистые решения, но не полностью переносимы из одной системы в другую, даже если вы используете одну и ту же оболочку на каждой. (Хотя seq становится все более доступным; например, во FreeBSD 9.3 и выше.) eval и другие формы косвенного обращения всегда работают, но несколько неэлегантны.

К счастью, bash поддерживает циклы в стиле C (с арифметическими только выражения). Итак, вот краткий способ "чистого bash":

repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }

Это принимает количество повторений в качестве первого аргумента и строку, которую нужно повторить (которая может быть одним символом, как в описании проблемы), в качестве второго аргумента. repecho 7 b выводит bbbbbbb (заканчивается новой строкой).

Деннис Уильямсон дал по существу это решение четыре года назад в его превосходном ответе на Создание строки повторяющихся символы в сценарии оболочки. Тело моей функции немного отличается от приведенного там кода:

Если $n - желаемое количество повторений, и вам не нужно его повторно использовать, и вы хотите что-то еще короче:

while ((n--)); do echo -n "$s"; done; echo

n должен быть переменной - этот способ не работает с позиционными параметрами. $s - текст, который нужно повторить.

person Eliah Kagan    schedule 19.09.2014
comment
Категорически избегайте использования циклических версий. printf "%100s" | tr ' ' '=' оптимально. - person ocodo; 04.11.2014
comment
Хорошая справочная информация и похвалы за упаковку функциональности как функции, которая, кстати, также работает в zsh. Подход «эхо-в-цикле» хорошо работает для меньшего количества повторов, но для большего количества есть POSIX-совместимые альтернативы на основе утилит, о чем свидетельствует комментарий @ Slomojo. - person mklement0; 29.04.2015
comment
Добавление круглых скобок вокруг вашего более короткого цикла сохраняет значение n, не влияя на эхо: (while ((n--)); do echo -n "$s"; done; echo) - person ; 23.08.2015
comment
используйте printf вместо echo! он более переносимый (echo -n может работать только в некоторых системах). см. unix.stackexchange .com / questions / 65803 / (один из замечательных ответов Стефана Чазеласа) - person Olivier Dulac; 13.02.2020
comment
@OlivierDulac Речь идет о bash. Независимо от того, в какой операционной системе вы работаете, если вы используете на ней bash, bash имеет встроенную echo, которая поддерживает -n. Смысл того, что вы говорите, абсолютно правильный. printf почти всегда следует предпочесть echo, по крайней мере, при неинтерактивном использовании. Но я не думаю, что было каким-либо образом неуместным или вводящим в заблуждение echo ответ на вопрос, в котором был задан один и который дал достаточно информации, чтобы знать, что это сработает. Также обратите внимание, что поддержка ((n--)) (без $) сама по себе не гарантируется POSIX. - person Eliah Kagan; 14.02.2020
comment
@EliahKagan Я никогда не говорил, что давать эхо-ответ неуместно или вводить в заблуждение, я предупреждаю, что мы (все) должны придерживаться использования printf вместо echo, поскольку printf более портативен (+ он позволяет избежать множества побочных эффектов в зависимости от начала вещь повторилась (минусы и т. д.), см. ответ Стефана). + таким образом ответ не ограничивается оболочками bash и аналогичными (кстати, OP сказал bash, но мог иметь в виду оболочку) - person Olivier Dulac; 14.02.2020

Python повсеместен и везде работает одинаково.

python -c "import sys; print('*' * int(sys.argv[1]))" "=" 100

Символ и количество передаются как отдельные параметры.

person loevborg    schedule 01.03.2018
comment
Я думаю, что это было намерением здесь python -c "import sys; print(sys.argv[1] * int(sys.argv[2]))" "=" 100 - person gazhay; 21.02.2020
comment
@loevborg разве не надуманный? - person Sapphire_Brick; 19.03.2020

В случае, если вы хотите повторить символ n раз, будучи n ПЕРЕМЕННОЙ количество раз в зависимости, скажем, от длины строки, вы можете:

#!/bin/bash
vari='AB'
n=$(expr 10 - length $vari)
echo 'vari equals.............................: '$vari
echo 'Up to 10 positions I must fill with.....: '$n' equal signs'
echo $vari$(perl -E 'say "=" x '$n)

Он отображает:

vari equals.............................: AB  
Up to 10 positions I must fill with.....: 8 equal signs  
AB========  
person Raul Baron    schedule 30.05.2013
comment
length не будет работать с expr, вы, вероятно, имели в виду n=$(expr 10 - ${#vari}); однако проще и эффективнее использовать арифметическое расширение Bash: n=$(( 10 - ${#vari} )). Кроме того, в основе вашего ответа лежит тот самый подход Perl, которому OP ищет альтернативу Bash. - person mklement0; 07.08.2015

Это более длинная версия того, что поддерживал Элиа Каган:

while [ $(( i-- )) -gt 0 ]; do echo -n "  "; done

Конечно, вы можете использовать и printf для этого, но мне это не очень нравится:

printf "%$(( i*2 ))s"

Эта версия совместима с Dash:

until [ $(( i=i-1 )) -lt 0 ]; do echo -n "  "; done

где i - начальное число.

person Xennex81    schedule 02.04.2015
comment
В bash и с положительным n: while (( i-- )); do echo -n " "; done работает. - person ; 23.08.2015

Самый простой - использовать этот однострочник в csh / tcsh:

printf "%50s\n" '' | tr '[:blank:]' '[=]'

person Shawn Givler    schedule 31.12.2018
comment
или bash как printf% 50s \ n | tr '' = - person Josiah; 01.03.2021

Другой вариант - использовать GNU seq и удалить все генерируемые числа и символы новой строки:

seq -f'#%.0f' 100 | tr -d '\n0123456789'

Эта команда печатает символ # 100 раз.

person sigalor    schedule 07.06.2019
comment
Нет необходимости в .f: echo $(seq -f'#' 100 | tr -d '\n') - person Coroos; 11.09.2020

Не для того, чтобы нагромождать, но другой подход, основанный на чистом Bash, использует ${//} подстановку массивов:

$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================
person dimo414    schedule 25.05.2020

function repeatString()
{
    local -r string="${1}"
    local -r numberToRepeat="${2}"

    if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
    then
        local -r result="$(printf "%${numberToRepeat}s")"
        echo -e "${result// /${string}}"
    fi
}

Примеры прогонов

$ repeatString 'a1' 10 
a1a1a1a1a1a1a1a1a1a1

$ repeatString 'a1' 0 

$ repeatString '' 10 

Справочная библиотека по адресу: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

person Nam Nguyen    schedule 08.03.2018

Как я мог сделать это с помощью эха?

Вы можете сделать это с помощью echo, если за echo следует sed:

echo | sed -r ':a s/^(.*)$/=\1/; /^={100}$/q; ba'

Собственно, в этом echo нет необходимости.

person DaBler    schedule 01.02.2019

Мой ответ немного сложнее и, вероятно, не идеален, но для тех, кто хочет выводить большие числа, я смог сделать около 10 миллионов за 3 секунды.

repeatString(){
    # argument 1: The string to print
    # argument 2: The number of times to print
    stringToPrint=$1
    length=$2

    # Find the largest integer value of x in 2^x=(number of times to repeat) using logarithms
    power=`echo "l(${length})/l(2)" | bc -l`
    power=`echo "scale=0; ${power}/1" | bc`

    # Get the difference between the length and 2^x
    diff=`echo "${length} - 2^${power}" | bc`

    # Double the string length to the power of x
    for i in `seq "${power}"`; do 
        stringToPrint="${stringToPrint}${stringToPrint}"
    done

    #Since we know that the string is now at least bigger than half the total, grab however many more we need and add it to the string.
    stringToPrint="${stringToPrint}${stringToPrint:0:${diff}}"
    echo ${stringToPrint}
}
person Silver Ogre    schedule 23.02.2019

Самый простой - использовать этот однострочник в bash:

seq 10 | xargs -n 1 | xargs -I {} echo -n  ===\>;echo

person shahin aref    schedule 27.03.2019

Более элегантной альтернативой предлагаемому решению Python может быть:

python -c 'print "="*(1000)'
person Anas Tiour    schedule 22.05.2019

Большинство существующих решений зависят от {1..10} поддержки синтаксиса оболочки, которая зависит от bash и zsh, и не работает в tcsh или OpenBSD _ 5_ и большинство не-bash sh.

Следующее должно работать в OS X и всех системах * BSD в любой оболочке; по сути, с его помощью можно сформировать целую матрицу различных видов декоративного пространства:

$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$ 

К сожалению, мы не получаем завершающего символа новой строки; что может быть исправлено дополнительным printf '\n' после сгиба:

$ printf "=%.0s" `jot 64` | fold -16 ; printf "\n"
================
================
================
================
$ 

Использованная литература:

person cnst    schedule 13.08.2019

Мое предложение (принимает значения переменной для n):

n=100
seq 1 $n | xargs -I {} printf =
person Sopalajo de Arrierez    schedule 26.03.2020
comment
чем ваш xargs отличается от sed - person stack0114106; 12.07.2020
comment
это было на удивление медленно, но дало мне переменную для длины и печатаемого символа, которые я хотел. - person Josiah; 01.03.2021

Немного более длинная версия, но если вам по какой-то причине нужно использовать чистый Bash, вы можете использовать цикл while с увеличивающейся переменной:

n=0; while [ $n -lt 100 ]; do n=$((n+1)); echo -n '='; done
person Luke Mlsna    schedule 10.12.2020

printf -- '=%.0s' {1..100}

Двойное тире -- означает конец флагов командной строки, поэтому не пытайтесь разбирать то, что идет после параметров командной строки.

Если вы хотите напечатать символ тире -, а не символ =, несколько раз и не включать двойной тире --, вот что вы получите:

$ printf '-%.0s' {1..100}
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]

Почему бы не создать такую ​​однострочную функцию:

function repeat() { num="${2:-100}"; printf -- "$1%.0s" $(seq 1 $num); }

Тогда вы можете назвать это так:

$ repeat -
----------------------------------------------------------------------------------------------------

или вот так:

$ repeat =
====================================================================================================

или вот так:

$ repeat '*' 8
********
person l3x    schedule 23.06.2021

n=5; chr='x'; chr_string='';
for (( i=0; $i<$n; i++ ))
do
    chr_string=$chr_string$chr
done
echo -n "$chr_string"

Работает для ...
n = целое число (включая ноль и отрицательное число).
chr = печатаемое и пробел (пробел и табуляция).

person NOYB    schedule 07.09.2020