How can I repeat a character in Bash?












185















How could I do this with echo?



perl -E 'say "=" x 100'









share|improve this question




















  • 1





    possible duplicate of shell script create string of repeated characters

    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 10 '14 at 10:54











  • Sadly this is not Bash.

    – solidsnack
    Feb 20 '16 at 20:42






  • 1





    not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

    – Evgeny
    Apr 20 '17 at 15:53








  • 1





    Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

    – Dr Beco
    Jul 7 '17 at 5:21


















185















How could I do this with echo?



perl -E 'say "=" x 100'









share|improve this question




















  • 1





    possible duplicate of shell script create string of repeated characters

    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 10 '14 at 10:54











  • Sadly this is not Bash.

    – solidsnack
    Feb 20 '16 at 20:42






  • 1





    not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

    – Evgeny
    Apr 20 '17 at 15:53








  • 1





    Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

    – Dr Beco
    Jul 7 '17 at 5:21
















185












185








185


53






How could I do this with echo?



perl -E 'say "=" x 100'









share|improve this question
















How could I do this with echo?



perl -E 'say "=" x 100'






bash shell echo






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Feb 1 at 13:13









Mateusz Piotrowski

3,95063152




3,95063152










asked Mar 18 '11 at 8:45









sid_comsid_com

9,3021879152




9,3021879152








  • 1





    possible duplicate of shell script create string of repeated characters

    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 10 '14 at 10:54











  • Sadly this is not Bash.

    – solidsnack
    Feb 20 '16 at 20:42






  • 1





    not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

    – Evgeny
    Apr 20 '17 at 15:53








  • 1





    Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

    – Dr Beco
    Jul 7 '17 at 5:21
















  • 1





    possible duplicate of shell script create string of repeated characters

    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 10 '14 at 10:54











  • Sadly this is not Bash.

    – solidsnack
    Feb 20 '16 at 20:42






  • 1





    not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

    – Evgeny
    Apr 20 '17 at 15:53








  • 1





    Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

    – Dr Beco
    Jul 7 '17 at 5:21










1




1





possible duplicate of shell script create string of repeated characters

– Ciro Santilli 新疆改造中心 六四事件 法轮功
Apr 10 '14 at 10:54





possible duplicate of shell script create string of repeated characters

– Ciro Santilli 新疆改造中心 六四事件 法轮功
Apr 10 '14 at 10:54













Sadly this is not Bash.

– solidsnack
Feb 20 '16 at 20:42





Sadly this is not Bash.

– solidsnack
Feb 20 '16 at 20:42




1




1





not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

– Evgeny
Apr 20 '17 at 15:53







not with echo, but on the same topic ruby -e 'puts "=" * 100' or python -c 'print "=" * 100'

– Evgeny
Apr 20 '17 at 15:53






1




1





Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

– Dr Beco
Jul 7 '17 at 5:21







Great question. Very good answers. I've used one of the answers in a real job here, that I'll post as an example: github.com/drbeco/oldfiles/blob/master/oldfiles (used printf with seq) svrb=`printf '%.sv' $(seq $vrb)`

– Dr Beco
Jul 7 '17 at 5:21














23 Answers
23






active

oldest

votes


















308














You can use:



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


How this works:



Bash expands {1..100} so the command becomes:



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


I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.






share|improve this answer





















  • 11





    Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

    – mklement0
    Dec 7 '13 at 21:34






  • 4





    Is it possible to set the upper limit using a var? I've tried and can't get it to work.

    – Mike Purcell
    Jan 10 '14 at 20:30






  • 54





    You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

    – dogbane
    Jan 11 '14 at 8:22






  • 10





    If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

    – KomodoDave
    Jul 30 '14 at 7:35






  • 2





    This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

    – Jeenu
    Jan 8 '15 at 10:25



















76














No easy way. But for example:



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


Or maybe a standard-conforming way:



printf %100s |tr " " "="


There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)






share|improve this answer





















  • 2





    Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

    – Camilo Martin
    Jan 2 '14 at 16:10






  • 11





    printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

    – Ciro Santilli 新疆改造中心 六四事件 法轮功
    Apr 10 '14 at 11:02








  • 2





    To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

    – John Rix
    Sep 11 '14 at 12:51






  • 1





    +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

    – musiphil
    Mar 16 '15 at 20:59






  • 2





    @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

    – Camilo Martin
    May 3 '15 at 20:17



















38














There's more than one way to do it.



Using a loop:





  • Brace expansion can be used with integer literals:



    for i in {1..100}; do echo -n =; done    



  • A C-like loop allows the use of variables:



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



Using the printf builtin:



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


Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.



Using head (printf, etc) and tr:



head -c 100 < /dev/zero | tr '' '='
printf %100s | tr " " "="





share|improve this answer





















  • 1





    ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

    – mklement0
    Apr 29 '15 at 17:42













  • Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

    – loxaxs
    May 27 '18 at 9:09













  • Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

    – Michael Goldshteyn
    Aug 10 '18 at 23:10













  • For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

    – 3ED
    Aug 18 '18 at 16:26





















35














Tip of the hat to @gniourf_gniourf for his input.



Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.



Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).



Summary:




  • 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.




The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.



The entries are:




  • listed in ascending order of execution duration (fastest first)

  • prefixed with:



    • M ... a potentially multi-character solution


    • S ... a single-character-only solution


    • P ... a POSIX-compliant solution



  • followed by a brief description of the solution

  • suffixed with the name of the author of the originating answer





  • Small repeat count: 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



  • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).

  • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.





  • Large repeat count: 1000000 (1 million)


[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



  • The Perl solution from the question is by far the fastest.

  • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).

  • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.


  • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.

  • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.




Here's the Bash script (testrepeat) that produced the above.
It takes 2 arguments:




  • the character repeat count

  • optionally, the number of test runs to perform and to calculate the average timing from


In other words: the timings above were obtained with testrepeat 100 1000 and 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 '' '=' >"$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 '' "=" >"$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 "%st", $1;
if ($2 ~ "^n/a") { print $2 } else { printf "%.4fn", $2 / count }}' |
column -s$'t' -t





share|improve this answer


























  • It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

    – Sergiy Kolodyazhnyy
    Jan 19 '17 at 4:25



















25














I've just found a seriously easy way to do this using seq:



UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions



seq  -f "#" -s '' 10


Will print '#' 10 times, like this:



##########




  • -f "#" sets the format string to ignore the numbers and just print # for each one.


  • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number

  • The spaces after -f and -s seem to be important.


EDIT: Here it is in a handy function...



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


Which you can call like this...



repeat "#" 10


NOTE: If you're repeating # then the quotes are important!






share|improve this answer





















  • 7





    This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

    – John B
    Jul 7 '14 at 8:51











  • Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

    – Sam Salisbury
    Jul 8 '14 at 9:20











  • I'm using seq from GNU coreutils.

    – John B
    Jul 8 '14 at 11:38






  • 1





    @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

    – mklement0
    Apr 29 '15 at 17:18











  • Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

    – mklement0
    Apr 29 '15 at 17:30





















16














Here's two interesting ways:




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


Note these two are subtly different - The paste method ends in a new line. The tr method does not.






share|improve this answer



















  • 1





    Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

    – mklement0
    Apr 29 '15 at 13:56











  • Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

    – bishop
    Apr 27 '16 at 19:42











  • @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

    – mklement0
    Jul 17 '16 at 6:44



















11














There is no simple way. Avoid loops using printf and substitution.



str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.





share|improve this answer





















  • 2





    Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

    – mklement0
    Dec 7 '13 at 18:42






  • 1





    @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

    – Camilo Martin
    Jan 2 '14 at 12:16



















7
















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


Or



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


Example






share|improve this answer





















  • 3





    Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

    – mklement0
    Apr 29 '15 at 18:12








  • 1





    The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

    – mklement0
    May 14 '15 at 19:01











  • Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

    – user2350426
    Aug 25 '15 at 4:54






  • 2





    Note to users - original-awk is non standard and not recommended

    – Steven Penny
    Aug 25 '15 at 23:02











  • An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

    – oliv
    May 24 '18 at 13:16



















5














If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just 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)


...will produce the same output as perl -E 'say "=" x 100' just about everywhere.






share|improve this answer





















  • 1





    The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

    – mklement0
    Apr 29 '15 at 17:56






  • 1





    Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

    – Geoff Nixon
    May 3 '15 at 14:52



















4














I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command



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



for instance, prints a window-wide line of ////////////






share|improve this answer



















  • 2





    Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

    – mklement0
    Apr 29 '15 at 17:49








  • 1





    Thanks, I like your use of -s '' even better. I've changed my scripts.

    – Stefan Ludwig
    Apr 29 '15 at 21:47











  • On recent Debian-based systems, apt install athena-jot would provide jot.

    – agc
    Feb 8 at 20:54



















4














As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.



Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:



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


This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).



Dennis Williamson gave essentially this solution four years ago in his excellent answer to Creating string of repeated characters in shell script. My function body differs slightly from the code there:





  • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.



    Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)



  • Here the task is to print the sequence; there, it was to assign it to a variable.



If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:



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


n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.






share|improve this answer





















  • 1





    Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

    – ocodo
    Nov 4 '14 at 5:48













  • Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

    – mklement0
    Apr 29 '15 at 15:53













  • Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

    – user2350426
    Aug 23 '15 at 4:24



















3














A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):



If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,



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


You can make a function with this:



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}"
}


With this set:



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




For this little trick we're using printf quite a lot with:





  • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.

  • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.

  • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.




You can also get rid of the tmp variable in the repeat function by using indirect expansion:



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





share|improve this answer
























  • Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

    – mklement0
    Apr 29 '15 at 19:19











  • It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

    – mklement0
    Apr 29 '15 at 19:19





















2














In bash 3.0 or higher



for i in {1..100};do echo -n =;done





share|improve this answer































    2














    for i in {1..100}
    do
    echo -n '='
    done
    echo





    share|improve this answer































      2














      repeat() {
      # $1=number of patterns to repeat
      # $2=pattern
      printf -v "TEMP" '%*s' "$1"
      echo ${TEMP// /$2}
      }





      share|improve this answer

































        2














        The question was about how to do it with echo:



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


        This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.






        share|improve this answer

































          1














          In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:



          #!/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)


          It displays:



          vari equals.............................: AB  
          Up to 10 positions I must fill with.....: 8 equal signs
          AB========





          share|improve this answer


























          • length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

            – mklement0
            Aug 7 '15 at 12:55



















          1














          This is the longer version of what Eliah Kagan was espousing:



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


          Of course you can use printf for that as well, but not really to my liking:



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


          This version is Dash compatible:



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


          with i being the initial number.






          share|improve this answer
























          • In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

            – user2350426
            Aug 23 '15 at 4:27



















          1














          Python is ubiquitous and works the same everywhere.




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



          Character and count are passed as separate parameters.






          share|improve this answer































            1















            How could I do this with echo?




            You can do this with echo if the echo is followed by sed:



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


            Actually, that echo is unnecessary there.






            share|improve this answer































              0














              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
              }


              Sample runs



              $ repeatString 'a1' 10 
              a1a1a1a1a1a1a1a1a1a1

              $ repeatString 'a1' 0

              $ repeatString '' 10


              Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash






              share|improve this answer































                0














                Simplest is to use this one-liner in csh/tcsh:



                printf "%50sn" '' | tr '[:blank:]' '[=]'








                share|improve this answer

































                  0














                  My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.



                  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}
                  }





                  share|improve this answer























                    Your Answer






                    StackExchange.ifUsing("editor", function () {
                    StackExchange.using("externalEditor", function () {
                    StackExchange.using("snippets", function () {
                    StackExchange.snippets.init();
                    });
                    });
                    }, "code-snippets");

                    StackExchange.ready(function() {
                    var channelOptions = {
                    tags: "".split(" "),
                    id: "1"
                    };
                    initTagRenderer("".split(" "), "".split(" "), channelOptions);

                    StackExchange.using("externalEditor", function() {
                    // Have to fire editor after snippets, if snippets enabled
                    if (StackExchange.settings.snippets.snippetsEnabled) {
                    StackExchange.using("snippets", function() {
                    createEditor();
                    });
                    }
                    else {
                    createEditor();
                    }
                    });

                    function createEditor() {
                    StackExchange.prepareEditor({
                    heartbeatType: 'answer',
                    autoActivateHeartbeat: false,
                    convertImagesToLinks: true,
                    noModals: true,
                    showLowRepImageUploadWarning: true,
                    reputationToPostImages: 10,
                    bindNavPrevention: true,
                    postfix: "",
                    imageUploader: {
                    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
                    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
                    allowUrls: true
                    },
                    onDemand: true,
                    discardSelector: ".discard-answer"
                    ,immediatelyShowMarkdownHelp:true
                    });


                    }
                    });














                    draft saved

                    draft discarded


















                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5349718%2fhow-can-i-repeat-a-character-in-bash%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown

























                    23 Answers
                    23






                    active

                    oldest

                    votes








                    23 Answers
                    23






                    active

                    oldest

                    votes









                    active

                    oldest

                    votes






                    active

                    oldest

                    votes









                    308














                    You can use:



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


                    How this works:



                    Bash expands {1..100} so the command becomes:



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


                    I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.






                    share|improve this answer





















                    • 11





                      Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                      – mklement0
                      Dec 7 '13 at 21:34






                    • 4





                      Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                      – Mike Purcell
                      Jan 10 '14 at 20:30






                    • 54





                      You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                      – dogbane
                      Jan 11 '14 at 8:22






                    • 10





                      If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                      – KomodoDave
                      Jul 30 '14 at 7:35






                    • 2





                      This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                      – Jeenu
                      Jan 8 '15 at 10:25
















                    308














                    You can use:



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


                    How this works:



                    Bash expands {1..100} so the command becomes:



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


                    I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.






                    share|improve this answer





















                    • 11





                      Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                      – mklement0
                      Dec 7 '13 at 21:34






                    • 4





                      Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                      – Mike Purcell
                      Jan 10 '14 at 20:30






                    • 54





                      You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                      – dogbane
                      Jan 11 '14 at 8:22






                    • 10





                      If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                      – KomodoDave
                      Jul 30 '14 at 7:35






                    • 2





                      This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                      – Jeenu
                      Jan 8 '15 at 10:25














                    308












                    308








                    308







                    You can use:



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


                    How this works:



                    Bash expands {1..100} so the command becomes:



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


                    I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.






                    share|improve this answer















                    You can use:



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


                    How this works:



                    Bash expands {1..100} so the command becomes:



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


                    I've set printf's format to =%.0s which means that it will always print a single = no matter what argument it is given. Therefore it prints 100 =s.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Mar 18 '11 at 9:28

























                    answered Mar 18 '11 at 8:58









                    dogbanedogbane

                    192k65320374




                    192k65320374








                    • 11





                      Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                      – mklement0
                      Dec 7 '13 at 21:34






                    • 4





                      Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                      – Mike Purcell
                      Jan 10 '14 at 20:30






                    • 54





                      You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                      – dogbane
                      Jan 11 '14 at 8:22






                    • 10





                      If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                      – KomodoDave
                      Jul 30 '14 at 7:35






                    • 2





                      This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                      – Jeenu
                      Jan 8 '15 at 10:25














                    • 11





                      Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                      – mklement0
                      Dec 7 '13 at 21:34






                    • 4





                      Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                      – Mike Purcell
                      Jan 10 '14 at 20:30






                    • 54





                      You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                      – dogbane
                      Jan 11 '14 at 8:22






                    • 10





                      If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                      – KomodoDave
                      Jul 30 '14 at 7:35






                    • 2





                      This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                      – Jeenu
                      Jan 8 '15 at 10:25








                    11




                    11





                    Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                    – mklement0
                    Dec 7 '13 at 21:34





                    Great solution that performs reasonably well even with large repeat counts. Here's a function wrapper you can invoke with repl = 100, for instance (eval trickery is required, unfortunately, for basing the brace expansion on a variable): repl() { printf "$1"'%.s' $(eval "echo {1.."$(($2))"}"); }

                    – mklement0
                    Dec 7 '13 at 21:34




                    4




                    4





                    Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                    – Mike Purcell
                    Jan 10 '14 at 20:30





                    Is it possible to set the upper limit using a var? I've tried and can't get it to work.

                    – Mike Purcell
                    Jan 10 '14 at 20:30




                    54




                    54





                    You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                    – dogbane
                    Jan 11 '14 at 8:22





                    You can't use variables within brace expansion. Use seq instead e.g. $(seq 1 $limit).

                    – dogbane
                    Jan 11 '14 at 8:22




                    10




                    10





                    If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                    – KomodoDave
                    Jul 30 '14 at 7:35





                    If you functionalise this it's best to rearrange it from $s%.0s to %.0s$s otherwise dashes cause a printf error.

                    – KomodoDave
                    Jul 30 '14 at 7:35




                    2




                    2





                    This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                    – Jeenu
                    Jan 8 '15 at 10:25





                    This made me notice a behaviour of Bash's printf: it continues to apply the format string until there are no arguments left. I had assumed it processed the format string only once!

                    – Jeenu
                    Jan 8 '15 at 10:25













                    76














                    No easy way. But for example:



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


                    Or maybe a standard-conforming way:



                    printf %100s |tr " " "="


                    There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)






                    share|improve this answer





















                    • 2





                      Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                      – Camilo Martin
                      Jan 2 '14 at 16:10






                    • 11





                      printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                      – Ciro Santilli 新疆改造中心 六四事件 法轮功
                      Apr 10 '14 at 11:02








                    • 2





                      To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                      – John Rix
                      Sep 11 '14 at 12:51






                    • 1





                      +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                      – musiphil
                      Mar 16 '15 at 20:59






                    • 2





                      @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                      – Camilo Martin
                      May 3 '15 at 20:17
















                    76














                    No easy way. But for example:



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


                    Or maybe a standard-conforming way:



                    printf %100s |tr " " "="


                    There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)






                    share|improve this answer





















                    • 2





                      Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                      – Camilo Martin
                      Jan 2 '14 at 16:10






                    • 11





                      printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                      – Ciro Santilli 新疆改造中心 六四事件 法轮功
                      Apr 10 '14 at 11:02








                    • 2





                      To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                      – John Rix
                      Sep 11 '14 at 12:51






                    • 1





                      +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                      – musiphil
                      Mar 16 '15 at 20:59






                    • 2





                      @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                      – Camilo Martin
                      May 3 '15 at 20:17














                    76












                    76








                    76







                    No easy way. But for example:



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


                    Or maybe a standard-conforming way:



                    printf %100s |tr " " "="


                    There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)






                    share|improve this answer















                    No easy way. But for example:



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


                    Or maybe a standard-conforming way:



                    printf %100s |tr " " "="


                    There's also a tput rep, but as for my terminals at hand (xterm and linux) they don't seem to support it:)







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Mar 18 '11 at 9:55

























                    answered Mar 18 '11 at 8:52







                    user332325















                    • 2





                      Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                      – Camilo Martin
                      Jan 2 '14 at 16:10






                    • 11





                      printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                      – Ciro Santilli 新疆改造中心 六四事件 法轮功
                      Apr 10 '14 at 11:02








                    • 2





                      To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                      – John Rix
                      Sep 11 '14 at 12:51






                    • 1





                      +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                      – musiphil
                      Mar 16 '15 at 20:59






                    • 2





                      @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                      – Camilo Martin
                      May 3 '15 at 20:17














                    • 2





                      Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                      – Camilo Martin
                      Jan 2 '14 at 16:10






                    • 11





                      printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                      – Ciro Santilli 新疆改造中心 六四事件 法轮功
                      Apr 10 '14 at 11:02








                    • 2





                      To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                      – John Rix
                      Sep 11 '14 at 12:51






                    • 1





                      +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                      – musiphil
                      Mar 16 '15 at 20:59






                    • 2





                      @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                      – Camilo Martin
                      May 3 '15 at 20:17








                    2




                    2





                    Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                    – Camilo Martin
                    Jan 2 '14 at 16:10





                    Note that the first option with seq prints one less than the number given, so that example will print 99 = characters.

                    – Camilo Martin
                    Jan 2 '14 at 16:10




                    11




                    11





                    printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                    – Ciro Santilli 新疆改造中心 六四事件 法轮功
                    Apr 10 '14 at 11:02







                    printf tr is the only POSIX solution because seq, yes and {1..3} are not POSIX.

                    – Ciro Santilli 新疆改造中心 六四事件 法轮功
                    Apr 10 '14 at 11:02






                    2




                    2





                    To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                    – John Rix
                    Sep 11 '14 at 12:51





                    To repeat a string rather than just a single character: printf %100s | sed 's/ /abc/g' - outputs 'abcabcabc...'

                    – John Rix
                    Sep 11 '14 at 12:51




                    1




                    1





                    +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                    – musiphil
                    Mar 16 '15 at 20:59





                    +1 for using no loops and only one external command (tr). You could also extend it to something like printf "%${COLUMNS}sn" | tr " " "=".

                    – musiphil
                    Mar 16 '15 at 20:59




                    2




                    2





                    @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                    – Camilo Martin
                    May 3 '15 at 20:17





                    @mklement0 Well, I was hoping you were counting the last newline by mistake with wc. The only conclusion I can take from this is "seq shouldn't be used".

                    – Camilo Martin
                    May 3 '15 at 20:17











                    38














                    There's more than one way to do it.



                    Using a loop:





                    • Brace expansion can be used with integer literals:



                      for i in {1..100}; do echo -n =; done    



                    • A C-like loop allows the use of variables:



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



                    Using the printf builtin:



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


                    Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.



                    Using head (printf, etc) and tr:



                    head -c 100 < /dev/zero | tr '' '='
                    printf %100s | tr " " "="





                    share|improve this answer





















                    • 1





                      ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                      – mklement0
                      Apr 29 '15 at 17:42













                    • Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                      – loxaxs
                      May 27 '18 at 9:09













                    • Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                      – Michael Goldshteyn
                      Aug 10 '18 at 23:10













                    • For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                      – 3ED
                      Aug 18 '18 at 16:26


















                    38














                    There's more than one way to do it.



                    Using a loop:





                    • Brace expansion can be used with integer literals:



                      for i in {1..100}; do echo -n =; done    



                    • A C-like loop allows the use of variables:



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



                    Using the printf builtin:



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


                    Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.



                    Using head (printf, etc) and tr:



                    head -c 100 < /dev/zero | tr '' '='
                    printf %100s | tr " " "="





                    share|improve this answer





















                    • 1





                      ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                      – mklement0
                      Apr 29 '15 at 17:42













                    • Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                      – loxaxs
                      May 27 '18 at 9:09













                    • Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                      – Michael Goldshteyn
                      Aug 10 '18 at 23:10













                    • For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                      – 3ED
                      Aug 18 '18 at 16:26
















                    38












                    38








                    38







                    There's more than one way to do it.



                    Using a loop:





                    • Brace expansion can be used with integer literals:



                      for i in {1..100}; do echo -n =; done    



                    • A C-like loop allows the use of variables:



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



                    Using the printf builtin:



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


                    Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.



                    Using head (printf, etc) and tr:



                    head -c 100 < /dev/zero | tr '' '='
                    printf %100s | tr " " "="





                    share|improve this answer















                    There's more than one way to do it.



                    Using a loop:





                    • Brace expansion can be used with integer literals:



                      for i in {1..100}; do echo -n =; done    



                    • A C-like loop allows the use of variables:



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



                    Using the printf builtin:



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


                    Specifying a precision here truncates the string to fit the specified width (0). As printf reuses the format string to consume all of the arguments, this simply prints "=" 100 times.



                    Using head (printf, etc) and tr:



                    head -c 100 < /dev/zero | tr '' '='
                    printf %100s | tr " " "="






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Aug 25 '16 at 11:02

























                    answered Mar 18 '11 at 8:50









                    Eugene YarmashEugene Yarmash

                    85.2k23184265




                    85.2k23184265








                    • 1





                      ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                      – mklement0
                      Apr 29 '15 at 17:42













                    • Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                      – loxaxs
                      May 27 '18 at 9:09













                    • Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                      – Michael Goldshteyn
                      Aug 10 '18 at 23:10













                    • For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                      – 3ED
                      Aug 18 '18 at 16:26
















                    • 1





                      ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                      – mklement0
                      Apr 29 '15 at 17:42













                    • Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                      – loxaxs
                      May 27 '18 at 9:09













                    • Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                      – Michael Goldshteyn
                      Aug 10 '18 at 23:10













                    • For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                      – 3ED
                      Aug 18 '18 at 16:26










                    1




                    1





                    ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                    – mklement0
                    Apr 29 '15 at 17:42







                    ++ for the head / tr solution, which works well even with high repeat counts (small caveat: head -c is not POSIX-compliant, but both BSD and GNU head implement it); while the other two solutions will be slow in that case, they do have the advantage of working with multi-character strings, too.

                    – mklement0
                    Apr 29 '15 at 17:42















                    Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                    – loxaxs
                    May 27 '18 at 9:09







                    Using yes and head -- useful if you want a certain number of newlines: yes "" | head -n 100. tr can make it print any character: yes "" | head -n 100 | tr "n" "="; echo

                    – loxaxs
                    May 27 '18 at 9:09















                    Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                    – Michael Goldshteyn
                    Aug 10 '18 at 23:10







                    Somewhat surprisingly: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null is significantly slower than the head -c100000000 < /dev/zero | tr '' '=' >/dev/null version. Of course you have to use a block size of 100M+ to measure the time difference reasonably. 100M bytes takes 1.7 s and 1 s with the two respective versions shown. I took off the tr and just dumped it to /dev/null and got 0.287 s for the head version and 0.675 s for the dd version for a billion bytes.

                    – Michael Goldshteyn
                    Aug 10 '18 at 23:10















                    For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                    – 3ED
                    Aug 18 '18 at 16:26







                    For: dd if=/dev/zero count=1 bs=100000000 | tr '' '=' >/dev/null => 0,21332 s, 469 MB/s; For: dd if=/dev/zero count=100 bs=1000000| tr '' '=' >/dev/null => 0,161579 s, 619 MB/s;

                    – 3ED
                    Aug 18 '18 at 16:26













                    35














                    Tip of the hat to @gniourf_gniourf for his input.



                    Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.



                    Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).



                    Summary:




                    • 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.




                    The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.



                    The entries are:




                    • listed in ascending order of execution duration (fastest first)

                    • prefixed with:



                      • M ... a potentially multi-character solution


                      • S ... a single-character-only solution


                      • P ... a POSIX-compliant solution



                    • followed by a brief description of the solution

                    • suffixed with the name of the author of the originating answer





                    • Small repeat count: 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



                    • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).

                    • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.





                    • Large repeat count: 1000000 (1 million)


                    [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



                    • The Perl solution from the question is by far the fastest.

                    • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).

                    • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.


                    • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.

                    • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.




                    Here's the Bash script (testrepeat) that produced the above.
                    It takes 2 arguments:




                    • the character repeat count

                    • optionally, the number of test runs to perform and to calculate the average timing from


                    In other words: the timings above were obtained with testrepeat 100 1000 and 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 '' '=' >"$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 '' "=" >"$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 "%st", $1;
                    if ($2 ~ "^n/a") { print $2 } else { printf "%.4fn", $2 / count }}' |
                    column -s$'t' -t





                    share|improve this answer


























                    • It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                      – Sergiy Kolodyazhnyy
                      Jan 19 '17 at 4:25
















                    35














                    Tip of the hat to @gniourf_gniourf for his input.



                    Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.



                    Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).



                    Summary:




                    • 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.




                    The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.



                    The entries are:




                    • listed in ascending order of execution duration (fastest first)

                    • prefixed with:



                      • M ... a potentially multi-character solution


                      • S ... a single-character-only solution


                      • P ... a POSIX-compliant solution



                    • followed by a brief description of the solution

                    • suffixed with the name of the author of the originating answer





                    • Small repeat count: 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



                    • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).

                    • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.





                    • Large repeat count: 1000000 (1 million)


                    [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



                    • The Perl solution from the question is by far the fastest.

                    • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).

                    • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.


                    • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.

                    • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.




                    Here's the Bash script (testrepeat) that produced the above.
                    It takes 2 arguments:




                    • the character repeat count

                    • optionally, the number of test runs to perform and to calculate the average timing from


                    In other words: the timings above were obtained with testrepeat 100 1000 and 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 '' '=' >"$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 '' "=" >"$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 "%st", $1;
                    if ($2 ~ "^n/a") { print $2 } else { printf "%.4fn", $2 / count }}' |
                    column -s$'t' -t





                    share|improve this answer


























                    • It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                      – Sergiy Kolodyazhnyy
                      Jan 19 '17 at 4:25














                    35












                    35








                    35







                    Tip of the hat to @gniourf_gniourf for his input.



                    Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.



                    Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).



                    Summary:




                    • 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.




                    The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.



                    The entries are:




                    • listed in ascending order of execution duration (fastest first)

                    • prefixed with:



                      • M ... a potentially multi-character solution


                      • S ... a single-character-only solution


                      • P ... a POSIX-compliant solution



                    • followed by a brief description of the solution

                    • suffixed with the name of the author of the originating answer





                    • Small repeat count: 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



                    • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).

                    • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.





                    • Large repeat count: 1000000 (1 million)


                    [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



                    • The Perl solution from the question is by far the fastest.

                    • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).

                    • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.


                    • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.

                    • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.




                    Here's the Bash script (testrepeat) that produced the above.
                    It takes 2 arguments:




                    • the character repeat count

                    • optionally, the number of test runs to perform and to calculate the average timing from


                    In other words: the timings above were obtained with testrepeat 100 1000 and 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 '' '=' >"$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 '' "=" >"$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 "%st", $1;
                    if ($2 ~ "^n/a") { print $2 } else { printf "%.4fn", $2 / count }}' |
                    column -s$'t' -t





                    share|improve this answer















                    Tip of the hat to @gniourf_gniourf for his input.



                    Note: This answer does not answer the original question, but complements the existing, helpful answers by comparing performance.



                    Solutions are compared in terms of execution speed only - memory requirements are not taken into account (they vary across solutions and may matter with large repeat counts).



                    Summary:




                    • 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.




                    The following are timings taken on a late-2012 iMac with a 3.2 GHz Intel Core i5 CPU and a Fusion Drive, running OSX 10.10.4 and bash 3.2.57, and are the average of 1000 runs.



                    The entries are:




                    • listed in ascending order of execution duration (fastest first)

                    • prefixed with:



                      • M ... a potentially multi-character solution


                      • S ... a single-character-only solution


                      • P ... a POSIX-compliant solution



                    • followed by a brief description of the solution

                    • suffixed with the name of the author of the originating answer





                    • Small repeat count: 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



                    • The Bash-only solutions lead the pack - but only with a repeat count this small! (see below).

                    • Startup cost of external utilities does matter here, especially Perl's. If you must call this in a loop - with small repetition counts in each iteration - avoid the multi-utility, awk, and perl solutions.





                    • Large repeat count: 1000000 (1 million)


                    [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



                    • The Perl solution from the question is by far the fastest.

                    • Bash's global string-replacement (${foo// /=}) is inexplicably excruciatingly slow with large strings, and has been taken out of the running (took around 50 minutes(!) in Bash 4.3.30, and even longer in Bash 3.2.57 - I never waited for it to finish).

                    • Bash loops are slow, and arithmetic loops ((( i= 0; ... ))) are slower than brace-expanded ones ({1..n}) - though arithmetic loops are more memory-efficient.


                    • awk refers to BSD awk (as also found on OSX) - it's noticeably slower than gawk (GNU Awk) and especially mawk.

                    • Note that with large counts and multi-char. strings, memory consumption can become a consideration - the approaches differ in that respect.




                    Here's the Bash script (testrepeat) that produced the above.
                    It takes 2 arguments:




                    • the character repeat count

                    • optionally, the number of test runs to perform and to calculate the average timing from


                    In other words: the timings above were obtained with testrepeat 100 1000 and 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 '' '=' >"$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 '' "=" >"$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 "%st", $1;
                    if ($2 ~ "^n/a") { print $2 } else { printf "%.4fn", $2 / count }}' |
                    column -s$'t' -t






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 23 '17 at 11:47









                    Community

                    11




                    11










                    answered May 17 '15 at 15:04









                    mklement0mklement0

                    133k21249287




                    133k21249287













                    • It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                      – Sergiy Kolodyazhnyy
                      Jan 19 '17 at 4:25



















                    • It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                      – Sergiy Kolodyazhnyy
                      Jan 19 '17 at 4:25

















                    It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                    – Sergiy Kolodyazhnyy
                    Jan 19 '17 at 4:25





                    It's interesting to see timing comparison, but I think in many programs output is buffered, so their timing can be altered if buffering was turned off.

                    – Sergiy Kolodyazhnyy
                    Jan 19 '17 at 4:25











                    25














                    I've just found a seriously easy way to do this using seq:



                    UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions



                    seq  -f "#" -s '' 10


                    Will print '#' 10 times, like this:



                    ##########




                    • -f "#" sets the format string to ignore the numbers and just print # for each one.


                    • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number

                    • The spaces after -f and -s seem to be important.


                    EDIT: Here it is in a handy function...



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


                    Which you can call like this...



                    repeat "#" 10


                    NOTE: If you're repeating # then the quotes are important!






                    share|improve this answer





















                    • 7





                      This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                      – John B
                      Jul 7 '14 at 8:51











                    • Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                      – Sam Salisbury
                      Jul 8 '14 at 9:20











                    • I'm using seq from GNU coreutils.

                      – John B
                      Jul 8 '14 at 11:38






                    • 1





                      @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                      – mklement0
                      Apr 29 '15 at 17:18











                    • Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                      – mklement0
                      Apr 29 '15 at 17:30


















                    25














                    I've just found a seriously easy way to do this using seq:



                    UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions



                    seq  -f "#" -s '' 10


                    Will print '#' 10 times, like this:



                    ##########




                    • -f "#" sets the format string to ignore the numbers and just print # for each one.


                    • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number

                    • The spaces after -f and -s seem to be important.


                    EDIT: Here it is in a handy function...



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


                    Which you can call like this...



                    repeat "#" 10


                    NOTE: If you're repeating # then the quotes are important!






                    share|improve this answer





















                    • 7





                      This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                      – John B
                      Jul 7 '14 at 8:51











                    • Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                      – Sam Salisbury
                      Jul 8 '14 at 9:20











                    • I'm using seq from GNU coreutils.

                      – John B
                      Jul 8 '14 at 11:38






                    • 1





                      @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                      – mklement0
                      Apr 29 '15 at 17:18











                    • Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                      – mklement0
                      Apr 29 '15 at 17:30
















                    25












                    25








                    25







                    I've just found a seriously easy way to do this using seq:



                    UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions



                    seq  -f "#" -s '' 10


                    Will print '#' 10 times, like this:



                    ##########




                    • -f "#" sets the format string to ignore the numbers and just print # for each one.


                    • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number

                    • The spaces after -f and -s seem to be important.


                    EDIT: Here it is in a handy function...



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


                    Which you can call like this...



                    repeat "#" 10


                    NOTE: If you're repeating # then the quotes are important!






                    share|improve this answer















                    I've just found a seriously easy way to do this using seq:



                    UPDATE: This works on the BSD seq that comes with OS X. YMMV with other versions



                    seq  -f "#" -s '' 10


                    Will print '#' 10 times, like this:



                    ##########




                    • -f "#" sets the format string to ignore the numbers and just print # for each one.


                    • -s '' sets the separator to an empty string to remove the newlines that seq inserts between each number

                    • The spaces after -f and -s seem to be important.


                    EDIT: Here it is in a handy function...



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


                    Which you can call like this...



                    repeat "#" 10


                    NOTE: If you're repeating # then the quotes are important!







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Apr 30 '15 at 0:54









                    Steven Penny

                    1




                    1










                    answered May 2 '14 at 11:04









                    Sam SalisburySam Salisbury

                    748715




                    748715








                    • 7





                      This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                      – John B
                      Jul 7 '14 at 8:51











                    • Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                      – Sam Salisbury
                      Jul 8 '14 at 9:20











                    • I'm using seq from GNU coreutils.

                      – John B
                      Jul 8 '14 at 11:38






                    • 1





                      @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                      – mklement0
                      Apr 29 '15 at 17:18











                    • Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                      – mklement0
                      Apr 29 '15 at 17:30
















                    • 7





                      This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                      – John B
                      Jul 7 '14 at 8:51











                    • Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                      – Sam Salisbury
                      Jul 8 '14 at 9:20











                    • I'm using seq from GNU coreutils.

                      – John B
                      Jul 8 '14 at 11:38






                    • 1





                      @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                      – mklement0
                      Apr 29 '15 at 17:18











                    • Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                      – mklement0
                      Apr 29 '15 at 17:30










                    7




                    7





                    This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                    – John B
                    Jul 7 '14 at 8:51





                    This gives me seq: format ‘#’ has no % directive. seq is for numbers, not strings. See gnu.org/software/coreutils/manual/html_node/seq-invocation.html

                    – John B
                    Jul 7 '14 at 8:51













                    Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                    – Sam Salisbury
                    Jul 8 '14 at 9:20





                    Ah, so I was using the BSD version of seq found on OS X. I'll update the answer. Which version are you using?

                    – Sam Salisbury
                    Jul 8 '14 at 9:20













                    I'm using seq from GNU coreutils.

                    – John B
                    Jul 8 '14 at 11:38





                    I'm using seq from GNU coreutils.

                    – John B
                    Jul 8 '14 at 11:38




                    1




                    1





                    @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                    – mklement0
                    Apr 29 '15 at 17:18





                    @JohnB: BSD seq is being cleverly repurposed here to replicate strings: the format string passed to -f - normally used to format the numbers being generated - contains only the string to replicate here so that the output contains copies of that string only. Unfortunately, GNU seq insists on the presence of a number format in the format string, which is the error you're seeing.

                    – mklement0
                    Apr 29 '15 at 17:18













                    Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                    – mklement0
                    Apr 29 '15 at 17:30







                    Nicely done; also works with multi-characters strings. Please use "$1" (double quotes), so you can also pass in characters such as '*' and strings with embedded whitespace. Finally, if you want to be able to use %, you have to double it (otherwise seq will think it's part of a format specification such as %f); using "${1//%/%%}" would take care of that. Since (as you mention) you're using BSD seq, this will work on BSD-like OSs in general (e.g., FreeBSD) - by contrast, it won't work on Linux, where GNU seq is used.

                    – mklement0
                    Apr 29 '15 at 17:30













                    16














                    Here's two interesting ways:




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


                    Note these two are subtly different - The paste method ends in a new line. The tr method does not.






                    share|improve this answer



















                    • 1





                      Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                      – mklement0
                      Apr 29 '15 at 13:56











                    • Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                      – bishop
                      Apr 27 '16 at 19:42











                    • @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                      – mklement0
                      Jul 17 '16 at 6:44
















                    16














                    Here's two interesting ways:




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


                    Note these two are subtly different - The paste method ends in a new line. The tr method does not.






                    share|improve this answer



















                    • 1





                      Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                      – mklement0
                      Apr 29 '15 at 13:56











                    • Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                      – bishop
                      Apr 27 '16 at 19:42











                    • @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                      – mklement0
                      Jul 17 '16 at 6:44














                    16












                    16








                    16







                    Here's two interesting ways:




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


                    Note these two are subtly different - The paste method ends in a new line. The tr method does not.






                    share|improve this answer













                    Here's two interesting ways:




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


                    Note these two are subtly different - The paste method ends in a new line. The tr method does not.







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 21 '13 at 15:37









                    Digital TraumaDigital Trauma

                    11.4k13369




                    11.4k13369








                    • 1





                      Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                      – mklement0
                      Apr 29 '15 at 13:56











                    • Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                      – bishop
                      Apr 27 '16 at 19:42











                    • @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                      – mklement0
                      Jul 17 '16 at 6:44














                    • 1





                      Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                      – mklement0
                      Apr 29 '15 at 13:56











                    • Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                      – bishop
                      Apr 27 '16 at 19:42











                    • @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                      – mklement0
                      Jul 17 '16 at 6:44








                    1




                    1





                    Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                    – mklement0
                    Apr 29 '15 at 13:56





                    Nicely done; please note that BSD paste inexplicably requires -d '' for specifying an empty delimiter, and fails with -d '' - -d '' should work wit all POSIX-compatible paste implementations and indeed works with GNU paste too.

                    – mklement0
                    Apr 29 '15 at 13:56













                    Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                    – bishop
                    Apr 27 '16 at 19:42





                    Similar in spirit, with fewer outboard tools: yes | mapfile -n 100 -C 'printf = #' -c 1

                    – bishop
                    Apr 27 '16 at 19:42













                    @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                    – mklement0
                    Jul 17 '16 at 6:44





                    @bishop: While your command indeed creates one fewer subshell, it is still slower for higher repeat counts, and for lower repeat counts the difference probably doesn't matter; the exact threshold is probably both hardware- and OS-dependent, e.g., on my OSX 10.11.5 machine this answer is already faster at 500; try time yes = | head -500 | paste -s -d '' -; time yes | mapfile -n 500 -C 'printf = #' -c 1. More importantly, however: if you're using printf anyway, you may as well go with the both simpler and more efficient approach from the accepted answer: printf '%.s=' $(seq 500)

                    – mklement0
                    Jul 17 '16 at 6:44











                    11














                    There is no simple way. Avoid loops using printf and substitution.



                    str=$(printf "%40s")
                    echo ${str// /rep}
                    # echoes "rep" 40 times.





                    share|improve this answer





















                    • 2





                      Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                      – mklement0
                      Dec 7 '13 at 18:42






                    • 1





                      @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                      – Camilo Martin
                      Jan 2 '14 at 12:16
















                    11














                    There is no simple way. Avoid loops using printf and substitution.



                    str=$(printf "%40s")
                    echo ${str// /rep}
                    # echoes "rep" 40 times.





                    share|improve this answer





















                    • 2





                      Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                      – mklement0
                      Dec 7 '13 at 18:42






                    • 1





                      @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                      – Camilo Martin
                      Jan 2 '14 at 12:16














                    11












                    11








                    11







                    There is no simple way. Avoid loops using printf and substitution.



                    str=$(printf "%40s")
                    echo ${str// /rep}
                    # echoes "rep" 40 times.





                    share|improve this answer















                    There is no simple way. Avoid loops using printf and substitution.



                    str=$(printf "%40s")
                    echo ${str// /rep}
                    # echoes "rep" 40 times.






                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Jun 1 '14 at 7:10









                    Steven Penny

                    1




                    1










                    answered Mar 18 '11 at 8:54









                    TimTim

                    9,90755393




                    9,90755393








                    • 2





                      Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                      – mklement0
                      Dec 7 '13 at 18:42






                    • 1





                      @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                      – Camilo Martin
                      Jan 2 '14 at 12:16














                    • 2





                      Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                      – mklement0
                      Dec 7 '13 at 18:42






                    • 1





                      @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                      – Camilo Martin
                      Jan 2 '14 at 12:16








                    2




                    2





                    Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                    – mklement0
                    Dec 7 '13 at 18:42





                    Nice, but only performs reasonably with small repeat counts. Here's a function wrapper that can be invoked as repl = 100, for instance (doesn't output a trailing n): repl() { local ts=$(printf "%${2}s"); printf %s "${ts// /$1}"; }

                    – mklement0
                    Dec 7 '13 at 18:42




                    1




                    1





                    @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                    – Camilo Martin
                    Jan 2 '14 at 12:16





                    @mklement0 Nice of you to provide function versions of both solutions, +1 on both!

                    – Camilo Martin
                    Jan 2 '14 at 12:16











                    7
















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


                    Or



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


                    Example






                    share|improve this answer





















                    • 3





                      Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                      – mklement0
                      Apr 29 '15 at 18:12








                    • 1





                      The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                      – mklement0
                      May 14 '15 at 19:01











                    • Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                      – user2350426
                      Aug 25 '15 at 4:54






                    • 2





                      Note to users - original-awk is non standard and not recommended

                      – Steven Penny
                      Aug 25 '15 at 23:02











                    • An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                      – oliv
                      May 24 '18 at 13:16
















                    7
















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


                    Or



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


                    Example






                    share|improve this answer





















                    • 3





                      Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                      – mklement0
                      Apr 29 '15 at 18:12








                    • 1





                      The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                      – mklement0
                      May 14 '15 at 19:01











                    • Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                      – user2350426
                      Aug 25 '15 at 4:54






                    • 2





                      Note to users - original-awk is non standard and not recommended

                      – Steven Penny
                      Aug 25 '15 at 23:02











                    • An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                      – oliv
                      May 24 '18 at 13:16














                    7












                    7








                    7









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


                    Or



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


                    Example






                    share|improve this answer

















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


                    Or



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


                    Example







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 14 '15 at 5:51

























                    answered Jun 1 '14 at 8:28









                    Steven PennySteven Penny

                    1




                    1








                    • 3





                      Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                      – mklement0
                      Apr 29 '15 at 18:12








                    • 1





                      The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                      – mklement0
                      May 14 '15 at 19:01











                    • Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                      – user2350426
                      Aug 25 '15 at 4:54






                    • 2





                      Note to users - original-awk is non standard and not recommended

                      – Steven Penny
                      Aug 25 '15 at 23:02











                    • An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                      – oliv
                      May 24 '18 at 13:16














                    • 3





                      Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                      – mklement0
                      Apr 29 '15 at 18:12








                    • 1





                      The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                      – mklement0
                      May 14 '15 at 19:01











                    • Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                      – user2350426
                      Aug 25 '15 at 4:54






                    • 2





                      Note to users - original-awk is non standard and not recommended

                      – Steven Penny
                      Aug 25 '15 at 23:02











                    • An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                      – oliv
                      May 24 '18 at 13:16








                    3




                    3





                    Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                    – mklement0
                    Apr 29 '15 at 18:12







                    Nicely done; this is POSIX-compliant and reasonably fast even with high repeat counts, while also supporting multi-character strings. Here's the shell version: awk 'BEGIN { while (c++ < 100) printf "=" }'. Wrapped into a parameterized shell function (invoke as repeat 100 =, for instance): repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { txt=substr(txt, 2); while (i++ < count) printf txt }'; }. (The dummy . prefix char and complementary substr call are needed to work around a bug in BSD awk, where passing a variable value that starts with = breaks the command.)

                    – mklement0
                    Apr 29 '15 at 18:12






                    1




                    1





                    The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                    – mklement0
                    May 14 '15 at 19:01





                    The NF = 100 solution is very clever (though to get 100 =, you must use NF = 101). The caveats are that it crashes BSD awk (but it's very fast with gawk and even faster with mawk), and that POSIX discusses neither assigning to NF, nor use of fields in BEGIN blocks. You can make it work in BSD awk as well with a slight tweak: awk 'BEGIN { OFS = "="; $101=""; print }' (but curiously, in BSD awk that isn't faster than the loop solution). As a parameterized shell solution: repeat() { awk -v count="$1" -v txt=".$2" 'BEGIN { OFS=substr(txt, 2); $(count+1)=""; print }'; }.

                    – mklement0
                    May 14 '15 at 19:01













                    Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                    – user2350426
                    Aug 25 '15 at 4:54





                    Note to users - The NF=100 trick causes a segment fault on older awk. The original-awk is the name under Linux of the older awk similar to BSD's awk, which has also been reported to crash, if you want to try this. Note that crashing is usually the first step toward finding an exploitable bug. This answer is so promoting insecure code.

                    – user2350426
                    Aug 25 '15 at 4:54




                    2




                    2





                    Note to users - original-awk is non standard and not recommended

                    – Steven Penny
                    Aug 25 '15 at 23:02





                    Note to users - original-awk is non standard and not recommended

                    – Steven Penny
                    Aug 25 '15 at 23:02













                    An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                    – oliv
                    May 24 '18 at 13:16





                    An alternative to the first code snippet can be awk NF=100 OFS='=' <<< "" (using bash and gawk)

                    – oliv
                    May 24 '18 at 13:16











                    5














                    If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just 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)


                    ...will produce the same output as perl -E 'say "=" x 100' just about everywhere.






                    share|improve this answer





















                    • 1





                      The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                      – mklement0
                      Apr 29 '15 at 17:56






                    • 1





                      Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                      – Geoff Nixon
                      May 3 '15 at 14:52
















                    5














                    If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just 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)


                    ...will produce the same output as perl -E 'say "=" x 100' just about everywhere.






                    share|improve this answer





















                    • 1





                      The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                      – mklement0
                      Apr 29 '15 at 17:56






                    • 1





                      Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                      – Geoff Nixon
                      May 3 '15 at 14:52














                    5












                    5








                    5







                    If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just 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)


                    ...will produce the same output as perl -E 'say "=" x 100' just about everywhere.






                    share|improve this answer















                    If you want POSIX-compliance and consistency across different implementations of echo and printf, and/or shells other than just 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)


                    ...will produce the same output as perl -E 'say "=" x 100' just about everywhere.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 3 '15 at 14:58

























                    answered Dec 7 '14 at 9:34









                    Geoff NixonGeoff Nixon

                    1,88211527




                    1,88211527








                    • 1





                      The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                      – mklement0
                      Apr 29 '15 at 17:56






                    • 1





                      Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                      – Geoff Nixon
                      May 3 '15 at 14:52














                    • 1





                      The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                      – mklement0
                      Apr 29 '15 at 17:56






                    • 1





                      Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                      – Geoff Nixon
                      May 3 '15 at 14:52








                    1




                    1





                    The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                    – mklement0
                    Apr 29 '15 at 17:56





                    The problem is that seq is not a POSIX utility (though BSD and Linux systems have implementations of it) - you can do POSIX shell arithmetic with a while loop instead, as in @Xennex81's answer (with printf "=", as you correctly suggest, rather than echo -n).

                    – mklement0
                    Apr 29 '15 at 17:56




                    1




                    1





                    Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                    – Geoff Nixon
                    May 3 '15 at 14:52





                    Oops, you're quite right. Things like that just slip past me sometimes as that standard makes no f'ing sense. cal is POSIX. seq is not. Anyway, rather than rewrite the answer with a while loop (as you say, that's already in other answers) I'll add a RYO function. More educational that way ;-).

                    – Geoff Nixon
                    May 3 '15 at 14:52











                    4














                    I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command



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



                    for instance, prints a window-wide line of ////////////






                    share|improve this answer



















                    • 2





                      Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                      – mklement0
                      Apr 29 '15 at 17:49








                    • 1





                      Thanks, I like your use of -s '' even better. I've changed my scripts.

                      – Stefan Ludwig
                      Apr 29 '15 at 21:47











                    • On recent Debian-based systems, apt install athena-jot would provide jot.

                      – agc
                      Feb 8 at 20:54
















                    4














                    I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command



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



                    for instance, prints a window-wide line of ////////////






                    share|improve this answer



















                    • 2





                      Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                      – mklement0
                      Apr 29 '15 at 17:49








                    • 1





                      Thanks, I like your use of -s '' even better. I've changed my scripts.

                      – Stefan Ludwig
                      Apr 29 '15 at 21:47











                    • On recent Debian-based systems, apt install athena-jot would provide jot.

                      – agc
                      Feb 8 at 20:54














                    4












                    4








                    4







                    I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command



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



                    for instance, prints a window-wide line of ////////////






                    share|improve this answer













                    I guess the original purpose of the question was to do this just with the shell's built-in commands. So for loops and printfs would be legitimate, while rep, perl, and also jot below would not. Still, the following command



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



                    for instance, prints a window-wide line of ////////////







                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Nov 21 '13 at 14:54









                    Stefan LudwigStefan Ludwig

                    1287




                    1287








                    • 2





                      Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                      – mklement0
                      Apr 29 '15 at 17:49








                    • 1





                      Thanks, I like your use of -s '' even better. I've changed my scripts.

                      – Stefan Ludwig
                      Apr 29 '15 at 21:47











                    • On recent Debian-based systems, apt install athena-jot would provide jot.

                      – agc
                      Feb 8 at 20:54














                    • 2





                      Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                      – mklement0
                      Apr 29 '15 at 17:49








                    • 1





                      Thanks, I like your use of -s '' even better. I've changed my scripts.

                      – Stefan Ludwig
                      Apr 29 '15 at 21:47











                    • On recent Debian-based systems, apt install athena-jot would provide jot.

                      – agc
                      Feb 8 at 20:54








                    2




                    2





                    Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                    – mklement0
                    Apr 29 '15 at 17:49







                    Nicely done; this works well even with high repeat counts (while also supporting multi-character strings). To better illustrate the approach, here's the equivalent of the OP's command: jot -s '' -b '=' 100. The caveat is that while BSD-like platforms, including OSX, come with jot, Linux distros do not.

                    – mklement0
                    Apr 29 '15 at 17:49






                    1




                    1





                    Thanks, I like your use of -s '' even better. I've changed my scripts.

                    – Stefan Ludwig
                    Apr 29 '15 at 21:47





                    Thanks, I like your use of -s '' even better. I've changed my scripts.

                    – Stefan Ludwig
                    Apr 29 '15 at 21:47













                    On recent Debian-based systems, apt install athena-jot would provide jot.

                    – agc
                    Feb 8 at 20:54





                    On recent Debian-based systems, apt install athena-jot would provide jot.

                    – agc
                    Feb 8 at 20:54











                    4














                    As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.



                    Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:



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


                    This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).



                    Dennis Williamson gave essentially this solution four years ago in his excellent answer to Creating string of repeated characters in shell script. My function body differs slightly from the code there:





                    • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.



                      Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)



                    • Here the task is to print the sequence; there, it was to assign it to a variable.



                    If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:



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


                    n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.






                    share|improve this answer





















                    • 1





                      Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                      – ocodo
                      Nov 4 '14 at 5:48













                    • Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                      – mklement0
                      Apr 29 '15 at 15:53













                    • Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                      – user2350426
                      Aug 23 '15 at 4:24
















                    4














                    As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.



                    Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:



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


                    This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).



                    Dennis Williamson gave essentially this solution four years ago in his excellent answer to Creating string of repeated characters in shell script. My function body differs slightly from the code there:





                    • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.



                      Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)



                    • Here the task is to print the sequence; there, it was to assign it to a variable.



                    If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:



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


                    n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.






                    share|improve this answer





















                    • 1





                      Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                      – ocodo
                      Nov 4 '14 at 5:48













                    • Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                      – mklement0
                      Apr 29 '15 at 15:53













                    • Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                      – user2350426
                      Aug 23 '15 at 4:24














                    4












                    4








                    4







                    As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.



                    Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:



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


                    This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).



                    Dennis Williamson gave essentially this solution four years ago in his excellent answer to Creating string of repeated characters in shell script. My function body differs slightly from the code there:





                    • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.



                      Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)



                    • Here the task is to print the sequence; there, it was to assign it to a variable.



                    If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:



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


                    n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.






                    share|improve this answer















                    As others have said, in bash brace expansion precedes parameter expansion, so {m,n} ranges can only contain literals. seq and jot provide clean solutions but aren't fully portable from one system to another, even if you're using the same shell on each. (Though seq is increasingly available; e.g., in FreeBSD 9.3 and higher.) eval and other forms of indirection always work but are somewhat inelegant.



                    Fortunately, bash supports C-style for loops (with arithmetic expressions only). So here's a concise "pure bash" way:



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


                    This takes the number of repetitions as the first argument and the string to be repeated (which may be a single character, as in the problem description) as the second argument. repecho 7 b outputs bbbbbbb (terminated by a newline).



                    Dennis Williamson gave essentially this solution four years ago in his excellent answer to Creating string of repeated characters in shell script. My function body differs slightly from the code there:





                    • Since the focus here is on repeating a single character and the shell is bash, it's probably safe to use echo instead of printf. And I read the problem description in this question as expressing a preference to print with echo. The above function definition works in bash and ksh93. Although printf is more portable (and should usually be used for this sort of thing), echo's syntax is arguably more readable.



                      Some shells' echo builtins interpret - by itself as an option--even though the usual meaning of -, to use stdin for input, is nonsensical for echo. zsh does this. And there definitely exist echos that don't recognize -n, as it is not standard. (Many Bourne-style shells don't accept C-style for loops at all, thus their echo behavior needn't be considered..)



                    • Here the task is to print the sequence; there, it was to assign it to a variable.



                    If $n is the desired number of repetitions and you don't have to reuse it, and you want something even shorter:



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


                    n must be a variable--this way doesn't work with positional parameters. $s is the text to be repeated.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited May 23 '17 at 12:34









                    Community

                    11




                    11










                    answered Sep 19 '14 at 14:23









                    Eliah KaganEliah Kagan

                    1,34721434




                    1,34721434








                    • 1





                      Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                      – ocodo
                      Nov 4 '14 at 5:48













                    • Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                      – mklement0
                      Apr 29 '15 at 15:53













                    • Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                      – user2350426
                      Aug 23 '15 at 4:24














                    • 1





                      Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                      – ocodo
                      Nov 4 '14 at 5:48













                    • Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                      – mklement0
                      Apr 29 '15 at 15:53













                    • Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                      – user2350426
                      Aug 23 '15 at 4:24








                    1




                    1





                    Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                    – ocodo
                    Nov 4 '14 at 5:48







                    Strongly avoid doing loop versions. printf "%100s" | tr ' ' '=' is optimal.

                    – ocodo
                    Nov 4 '14 at 5:48















                    Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                    – mklement0
                    Apr 29 '15 at 15:53







                    Good background info and kudos for packaging the functionality as a function, which works in zsh as well, incidentally. The echo-in-a-loop approach works well for smaller repeat counts, but for larger ones there are POSIX-compliant alternatives based on utilities, as evidenced by @Slomojo's comment.

                    – mklement0
                    Apr 29 '15 at 15:53















                    Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                    – user2350426
                    Aug 23 '15 at 4:24





                    Adding parentheses around your shorter loop preserves the value of n without affecting the echos: (while ((n--)); do echo -n "$s"; done; echo)

                    – user2350426
                    Aug 23 '15 at 4:24











                    3














                    A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):



                    If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,



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


                    You can make a function with this:



                    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}"
                    }


                    With this set:



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




                    For this little trick we're using printf quite a lot with:





                    • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.

                    • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.

                    • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.




                    You can also get rid of the tmp variable in the repeat function by using indirect expansion:



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





                    share|improve this answer
























                    • Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                      – mklement0
                      Apr 29 '15 at 19:19











                    • It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                      – mklement0
                      Apr 29 '15 at 19:19


















                    3














                    A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):



                    If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,



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


                    You can make a function with this:



                    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}"
                    }


                    With this set:



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




                    For this little trick we're using printf quite a lot with:





                    • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.

                    • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.

                    • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.




                    You can also get rid of the tmp variable in the repeat function by using indirect expansion:



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





                    share|improve this answer
























                    • Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                      – mklement0
                      Apr 29 '15 at 19:19











                    • It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                      – mklement0
                      Apr 29 '15 at 19:19
















                    3












                    3








                    3







                    A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):



                    If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,



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


                    You can make a function with this:



                    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}"
                    }


                    With this set:



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




                    For this little trick we're using printf quite a lot with:





                    • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.

                    • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.

                    • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.




                    You can also get rid of the tmp variable in the repeat function by using indirect expansion:



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





                    share|improve this answer













                    A pure Bash way with no eval, no subshells, no external tools, no brace expansions (i.e., you can have the number to repeat in a variable):



                    If you're given a variable n that expands to a (non-negative) number and a variable pattern, e.g.,



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


                    You can make a function with this:



                    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}"
                    }


                    With this set:



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




                    For this little trick we're using printf quite a lot with:





                    • -v varname: instead of printing to standard output, printf will put the content of the formatted string in variable varname.

                    • '%*s': printf will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42 will print 42 spaces.

                    • Finally, when we have the wanted number of spaces in our variable, we use a parameter expansion to replace all the spaces by our pattern: ${var// /$pattern} will expand to the expansion of var with all the spaces replaced by the expansion of $pattern.




                    You can also get rid of the tmp variable in the repeat function by using indirect expansion:



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






                    share|improve this answer












                    share|improve this answer



                    share|improve this answer










                    answered Jun 1 '14 at 9:15









                    gniourf_gniourfgniourf_gniourf

                    30.9k56683




                    30.9k56683













                    • Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                      – mklement0
                      Apr 29 '15 at 19:19











                    • It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                      – mklement0
                      Apr 29 '15 at 19:19





















                    • Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                      – mklement0
                      Apr 29 '15 at 19:19











                    • It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                      – mklement0
                      Apr 29 '15 at 19:19



















                    Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                    – mklement0
                    Apr 29 '15 at 19:19





                    Interesting variation to pass the variable name in. While this solution is fine for repeat counts up to around 1,000 (and thus probably fine for most real-life applications, if I were to guess), it gets very slow for higher counts (see next comment).

                    – mklement0
                    Apr 29 '15 at 19:19













                    It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                    – mklement0
                    Apr 29 '15 at 19:19







                    It seems that bash's global string replacement operations in the context of parameter expansion (${var//old/new}) are particularly slow: excruciatingly slow in bash 3.2.57, and slow in bash 4.3.30, at least on my OSX 10.10.3 system on a 3.2 Ghz Intel Core i5 machine: With a count of 1,000, things are slow (3.2.57) / fast (4.3.30): 0.1 / 0.004 seconds. Increasing the count to 10,000 yields strikingly different numbers: repeat 10000 = var takes around 80 seconds(!) in bash 3.2.57, and around 0.3 seconds in bash 4.3.30 (much faster than on 3.2.57, but still slow).

                    – mklement0
                    Apr 29 '15 at 19:19













                    2














                    In bash 3.0 or higher



                    for i in {1..100};do echo -n =;done





                    share|improve this answer




























                      2














                      In bash 3.0 or higher



                      for i in {1..100};do echo -n =;done





                      share|improve this answer


























                        2












                        2








                        2







                        In bash 3.0 or higher



                        for i in {1..100};do echo -n =;done





                        share|improve this answer













                        In bash 3.0 or higher



                        for i in {1..100};do echo -n =;done






                        share|improve this answer












                        share|improve this answer



                        share|improve this answer










                        answered Mar 18 '11 at 8:49









                        adnansadnans

                        298211




                        298211























                            2














                            for i in {1..100}
                            do
                            echo -n '='
                            done
                            echo





                            share|improve this answer




























                              2














                              for i in {1..100}
                              do
                              echo -n '='
                              done
                              echo





                              share|improve this answer


























                                2












                                2








                                2







                                for i in {1..100}
                                do
                                echo -n '='
                                done
                                echo





                                share|improve this answer













                                for i in {1..100}
                                do
                                echo -n '='
                                done
                                echo






                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered Mar 18 '11 at 8:50









                                Ignacio Vazquez-AbramsIgnacio Vazquez-Abrams

                                586k10610681169




                                586k10610681169























                                    2














                                    repeat() {
                                    # $1=number of patterns to repeat
                                    # $2=pattern
                                    printf -v "TEMP" '%*s' "$1"
                                    echo ${TEMP// /$2}
                                    }





                                    share|improve this answer






























                                      2














                                      repeat() {
                                      # $1=number of patterns to repeat
                                      # $2=pattern
                                      printf -v "TEMP" '%*s' "$1"
                                      echo ${TEMP// /$2}
                                      }





                                      share|improve this answer




























                                        2












                                        2








                                        2







                                        repeat() {
                                        # $1=number of patterns to repeat
                                        # $2=pattern
                                        printf -v "TEMP" '%*s' "$1"
                                        echo ${TEMP// /$2}
                                        }





                                        share|improve this answer















                                        repeat() {
                                        # $1=number of patterns to repeat
                                        # $2=pattern
                                        printf -v "TEMP" '%*s' "$1"
                                        echo ${TEMP// /$2}
                                        }






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Oct 31 '14 at 15:44









                                        ZoogieZork

                                        10.2k54142




                                        10.2k54142










                                        answered Oct 31 '14 at 15:22









                                        WSimpsonWSimpson

                                        39436




                                        39436























                                            2














                                            The question was about how to do it with echo:



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


                                            This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.






                                            share|improve this answer






























                                              2














                                              The question was about how to do it with echo:



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


                                              This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.






                                              share|improve this answer




























                                                2












                                                2








                                                2







                                                The question was about how to do it with echo:



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


                                                This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.






                                                share|improve this answer















                                                The question was about how to do it with echo:



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


                                                This will will do exactly the same as perl -E 'say "=" x 100' but with echo only.







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Jan 5 at 12:49

























                                                answered Jan 5 at 12:42









                                                chevallierchevallier

                                                3332519




                                                3332519























                                                    1














                                                    In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:



                                                    #!/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)


                                                    It displays:



                                                    vari equals.............................: AB  
                                                    Up to 10 positions I must fill with.....: 8 equal signs
                                                    AB========





                                                    share|improve this answer


























                                                    • length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                      – mklement0
                                                      Aug 7 '15 at 12:55
















                                                    1














                                                    In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:



                                                    #!/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)


                                                    It displays:



                                                    vari equals.............................: AB  
                                                    Up to 10 positions I must fill with.....: 8 equal signs
                                                    AB========





                                                    share|improve this answer


























                                                    • length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                      – mklement0
                                                      Aug 7 '15 at 12:55














                                                    1












                                                    1








                                                    1







                                                    In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:



                                                    #!/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)


                                                    It displays:



                                                    vari equals.............................: AB  
                                                    Up to 10 positions I must fill with.....: 8 equal signs
                                                    AB========





                                                    share|improve this answer















                                                    In case that you want to repeat a character n times being n a VARIABLE number of times depending on, say, the length of a string you can do:



                                                    #!/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)


                                                    It displays:



                                                    vari equals.............................: AB  
                                                    Up to 10 positions I must fill with.....: 8 equal signs
                                                    AB========






                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Jun 15 '14 at 3:17









                                                    Camilo Martin

                                                    19.3k1692140




                                                    19.3k1692140










                                                    answered May 30 '13 at 14:14









                                                    Raul BaronRaul Baron

                                                    415




                                                    415













                                                    • length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                      – mklement0
                                                      Aug 7 '15 at 12:55



















                                                    • length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                      – mklement0
                                                      Aug 7 '15 at 12:55

















                                                    length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                    – mklement0
                                                    Aug 7 '15 at 12:55





                                                    length won't work with expr, you probably meant n=$(expr 10 - ${#vari}); however, it's simpler and more efficient to use Bash's arithmetic expansion: n=$(( 10 - ${#vari} )). Also, at the core of your answer is the very Perl approach that the OP is looking for a Bash alternative to.

                                                    – mklement0
                                                    Aug 7 '15 at 12:55











                                                    1














                                                    This is the longer version of what Eliah Kagan was espousing:



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


                                                    Of course you can use printf for that as well, but not really to my liking:



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


                                                    This version is Dash compatible:



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


                                                    with i being the initial number.






                                                    share|improve this answer
























                                                    • In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                      – user2350426
                                                      Aug 23 '15 at 4:27
















                                                    1














                                                    This is the longer version of what Eliah Kagan was espousing:



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


                                                    Of course you can use printf for that as well, but not really to my liking:



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


                                                    This version is Dash compatible:



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


                                                    with i being the initial number.






                                                    share|improve this answer
























                                                    • In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                      – user2350426
                                                      Aug 23 '15 at 4:27














                                                    1












                                                    1








                                                    1







                                                    This is the longer version of what Eliah Kagan was espousing:



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


                                                    Of course you can use printf for that as well, but not really to my liking:



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


                                                    This version is Dash compatible:



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


                                                    with i being the initial number.






                                                    share|improve this answer













                                                    This is the longer version of what Eliah Kagan was espousing:



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


                                                    Of course you can use printf for that as well, but not really to my liking:



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


                                                    This version is Dash compatible:



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


                                                    with i being the initial number.







                                                    share|improve this answer












                                                    share|improve this answer



                                                    share|improve this answer










                                                    answered Apr 2 '15 at 23:33









                                                    Xennex81Xennex81

                                                    13415




                                                    13415













                                                    • In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                      – user2350426
                                                      Aug 23 '15 at 4:27



















                                                    • In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                      – user2350426
                                                      Aug 23 '15 at 4:27

















                                                    In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                    – user2350426
                                                    Aug 23 '15 at 4:27





                                                    In bash and with a positive n: while (( i-- )); do echo -n " "; done works.

                                                    – user2350426
                                                    Aug 23 '15 at 4:27











                                                    1














                                                    Python is ubiquitous and works the same everywhere.




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



                                                    Character and count are passed as separate parameters.






                                                    share|improve this answer




























                                                      1














                                                      Python is ubiquitous and works the same everywhere.




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



                                                      Character and count are passed as separate parameters.






                                                      share|improve this answer


























                                                        1












                                                        1








                                                        1







                                                        Python is ubiquitous and works the same everywhere.




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



                                                        Character and count are passed as separate parameters.






                                                        share|improve this answer













                                                        Python is ubiquitous and works the same everywhere.




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



                                                        Character and count are passed as separate parameters.







                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Mar 1 '18 at 0:16









                                                        loevborgloevborg

                                                        1,368916




                                                        1,368916























                                                            1















                                                            How could I do this with echo?




                                                            You can do this with echo if the echo is followed by sed:



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


                                                            Actually, that echo is unnecessary there.






                                                            share|improve this answer




























                                                              1















                                                              How could I do this with echo?




                                                              You can do this with echo if the echo is followed by sed:



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


                                                              Actually, that echo is unnecessary there.






                                                              share|improve this answer


























                                                                1












                                                                1








                                                                1








                                                                How could I do this with echo?




                                                                You can do this with echo if the echo is followed by sed:



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


                                                                Actually, that echo is unnecessary there.






                                                                share|improve this answer














                                                                How could I do this with echo?




                                                                You can do this with echo if the echo is followed by sed:



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


                                                                Actually, that echo is unnecessary there.







                                                                share|improve this answer












                                                                share|improve this answer



                                                                share|improve this answer










                                                                answered Feb 1 at 13:12









                                                                DaBlerDaBler

                                                                1,26221630




                                                                1,26221630























                                                                    0














                                                                    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
                                                                    }


                                                                    Sample runs



                                                                    $ repeatString 'a1' 10 
                                                                    a1a1a1a1a1a1a1a1a1a1

                                                                    $ repeatString 'a1' 0

                                                                    $ repeatString '' 10


                                                                    Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash






                                                                    share|improve this answer




























                                                                      0














                                                                      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
                                                                      }


                                                                      Sample runs



                                                                      $ repeatString 'a1' 10 
                                                                      a1a1a1a1a1a1a1a1a1a1

                                                                      $ repeatString 'a1' 0

                                                                      $ repeatString '' 10


                                                                      Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash






                                                                      share|improve this answer


























                                                                        0












                                                                        0








                                                                        0







                                                                        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
                                                                        }


                                                                        Sample runs



                                                                        $ repeatString 'a1' 10 
                                                                        a1a1a1a1a1a1a1a1a1a1

                                                                        $ repeatString 'a1' 0

                                                                        $ repeatString '' 10


                                                                        Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash






                                                                        share|improve this answer













                                                                        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
                                                                        }


                                                                        Sample runs



                                                                        $ repeatString 'a1' 10 
                                                                        a1a1a1a1a1a1a1a1a1a1

                                                                        $ repeatString 'a1' 0

                                                                        $ repeatString '' 10


                                                                        Reference lib at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash







                                                                        share|improve this answer












                                                                        share|improve this answer



                                                                        share|improve this answer










                                                                        answered Mar 8 '18 at 18:30









                                                                        Nam NguyenNam Nguyen

                                                                        2,67083663




                                                                        2,67083663























                                                                            0














                                                                            Simplest is to use this one-liner in csh/tcsh:



                                                                            printf "%50sn" '' | tr '[:blank:]' '[=]'








                                                                            share|improve this answer






























                                                                              0














                                                                              Simplest is to use this one-liner in csh/tcsh:



                                                                              printf "%50sn" '' | tr '[:blank:]' '[=]'








                                                                              share|improve this answer




























                                                                                0












                                                                                0








                                                                                0







                                                                                Simplest is to use this one-liner in csh/tcsh:



                                                                                printf "%50sn" '' | tr '[:blank:]' '[=]'








                                                                                share|improve this answer















                                                                                Simplest is to use this one-liner in csh/tcsh:



                                                                                printf "%50sn" '' | tr '[:blank:]' '[=]'









                                                                                share|improve this answer














                                                                                share|improve this answer



                                                                                share|improve this answer








                                                                                edited Jan 1 at 6:54









                                                                                double-beep

                                                                                2,69241028




                                                                                2,69241028










                                                                                answered Dec 31 '18 at 17:51









                                                                                Shawn GivlerShawn Givler

                                                                                1




                                                                                1























                                                                                    0














                                                                                    My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.



                                                                                    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}
                                                                                    }





                                                                                    share|improve this answer




























                                                                                      0














                                                                                      My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.



                                                                                      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}
                                                                                      }





                                                                                      share|improve this answer


























                                                                                        0












                                                                                        0








                                                                                        0







                                                                                        My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.



                                                                                        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}
                                                                                        }





                                                                                        share|improve this answer













                                                                                        My answer is a bit more complicated, and probably not perfect, but for those looking to output large numbers, I was able to do around 10 million in 3 seconds.



                                                                                        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}
                                                                                        }






                                                                                        share|improve this answer












                                                                                        share|improve this answer



                                                                                        share|improve this answer










                                                                                        answered Feb 23 at 7:50









                                                                                        Silver OgreSilver Ogre

                                                                                        1




                                                                                        1






























                                                                                            draft saved

                                                                                            draft discarded




















































                                                                                            Thanks for contributing an answer to Stack Overflow!


                                                                                            • Please be sure to answer the question. Provide details and share your research!

                                                                                            But avoid



                                                                                            • Asking for help, clarification, or responding to other answers.

                                                                                            • Making statements based on opinion; back them up with references or personal experience.


                                                                                            To learn more, see our tips on writing great answers.




                                                                                            draft saved


                                                                                            draft discarded














                                                                                            StackExchange.ready(
                                                                                            function () {
                                                                                            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f5349718%2fhow-can-i-repeat-a-character-in-bash%23new-answer', 'question_page');
                                                                                            }
                                                                                            );

                                                                                            Post as a guest















                                                                                            Required, but never shown





















































                                                                                            Required, but never shown














                                                                                            Required, but never shown












                                                                                            Required, but never shown







                                                                                            Required, but never shown

































                                                                                            Required, but never shown














                                                                                            Required, but never shown












                                                                                            Required, but never shown







                                                                                            Required, but never shown







                                                                                            Popular posts from this blog

                                                                                            MongoDB - Not Authorized To Execute Command

                                                                                            How to fix TextFormField cause rebuild widget in Flutter

                                                                                            Npm cannot find a required file even through it is in the searched directory