How could I do this with echo
?
perl -E 'say "=" x 100'
How could I do this with echo
?
perl -E 'say "=" x 100'
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.
No easy way. But for example:
seq -s= 100|tr -d '[:digit:]'
# Editor's note: This requires BSD seq, and breaks with GNU seq (see comments)
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:)
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:
${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:
M
... a potentially multi-character solutionS
... a single-character-only solutionP
... a POSIX-compliant solution[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
awk
, and perl
solutions.[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
${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).(( 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
.Here's the Bash script (testrepeat
) that produced the above.
It takes 2 arguments:
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 '\0' '=' >"$outFile"
done
title '[M ] seq -f [Sam Salisbury]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
seq -f '=' -s '' $COUNT_REPETITIONS >"$outFile"
done
title '[M ] jot -b [Stefan Ludwig]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
jot -s '' -b '=' $COUNT_REPETITIONS >"$outFile"
done
title '[M ] yes + head + tr [Digital Trauma]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
yes = | head -$COUNT_REPETITIONS | tr -d '\n' >"$outFile"
done
title '[M ] Perl [sid_com]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
perl -e "print \"=\" x $COUNT_REPETITIONS" >"$outFile"
done
title '[S, P] dd + tr [mklement0]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
dd if=/dev/zero bs=$COUNT_REPETITIONS count=1 2>/dev/null | tr '\0' "=" >"$outFile"
done
# !! On OSX, awk is BSD awk, and mawk and gawk were installed later.
# !! On Linux systems, awk may refer to either mawk or gawk.
for awkBin in awk mawk gawk; do
if [[ -x $(command -v $awkBin) ]]; then
title "[M ] $awkBin"' - $(count+1)="=" [Steven Penny (variant)]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
$awkBin -v count=$COUNT_REPETITIONS 'BEGIN { OFS="="; $(count+1)=""; print }' >"$outFile"
done
title "[M, P] $awkBin"' - while loop [Steven Penny]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
time for (( n = 0; n < COUNT_RUNS; n++ )); do
$awkBin -v count=$COUNT_REPETITIONS 'BEGIN { while (i++ < count) printf "=" }' >"$outFile"
done
fi
done
title '[M ] printf + bash global substr. replacement [Tim]'
[[ $outFile != '/dev/null' ]] && outFile="$outFilePrefix$((++ndx))"
# !! In Bash 4.3.30 a single run with repeat count of 1 million took almost
# !! 50 *minutes*(!) to complete; n Bash 3.2.57 it's seemingly even slower -
# !! didn't wait for it to finish.
# !! Thus, this test is skipped for counts that are likely to be much slower
# !! than the other tests.
skip=0
[[ $BASH_VERSINFO -le 3 && COUNT_REPETITIONS -gt 1000 ]] && skip=1
[[ $BASH_VERSINFO -eq 4 && COUNT_REPETITIONS -gt 10000 ]] && skip=1
if (( skip )); then
echo 'n/a' >&2
else
time for (( n = 0; n < COUNT_RUNS; n++ )); do
{ printf -v t "%${COUNT_REPETITIONS}s" '='; printf %s "${t// /=}"; } >"$outFile"
done
fi
} 2>&1 |
sort -t$'\t' -k2,2n |
awk -F $'\t' -v count=$COUNT_RUNS '{
printf "%s\t", $1;
if ($2 ~ "^n/a") { print $2 } else { printf "%.4f\n", $2 / count }}' |
column -s$'\t' -t
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 '\0' '='
printf %100s | tr " " "="
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-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!
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.
There is no simple way. Avoid loops using printf
and substitution.
str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
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.
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
.printf
will use the argument to print the corresponding number of spaces. E.g., printf '%*s' 42
will print 42 spaces.${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}"
}
#!/usr/bin/awk -f
BEGIN {
OFS = "="
NF = 100
print
}
Or
#!/usr/bin/awk -f
BEGIN {
while (z++ < 100) printf "="
}
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.
Here's what I use to print a line of characters across the screen in linux (based on terminal/screen width)
printf '=%.0s' $(seq 1 $(tput cols))
Explanation:
Print an equal sign as many times as the given sequence:
printf '=%.0s' #sequence
Use the output of a command (this is a bash feature called Command Substitution):
$(example_command)
Give a sequence, I've used 1 to 20 as an example. In the final command the tput command is used instead of 20:
seq 1 20
Give the number of columns currently used in the terminal:
tput cols
Another mean to repeat an arbitrary string n times:
Pros:
Cons:
yes
command.#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"
With an ANSI terminal and US-ASCII characters to repeat. You can use an ANSI CSI escape sequence. It is the fastest way to repeat a character.
#!/usr/bin/env bash
char='='
repeat_count=80
printf '%c\e[%db' "$char" "$repeat_count"
Or statically:
Print a line of 80 times =
:
printf '=\e[80b\n'
Limitations:
repeat_char
ANSI CSI sequence.repeat_char
ANSI CSI sequence into the repeated character.Another bash solution using printf and tr
nb. before I begin:
Use the leading-zero-padding feature of printf
and convert the zeroes using tr
. This avoids any {1..N}
generator:
$ printf '%040s' | tr '0' '='
========================================
To set the width to 'N' characters and customise the char printed:
#!/usr/bin/env bash
N=40
C='-'
printf "%0${N}s" | tr '0' "${C}"
For large N, this is quite a bit more performant than the generator; On my machine (bash 3.2.57):
$ time printf '=%.0s' {1..1000000} real: 0m2.580s
$ time printf '%01000000s' | tr '0' '=' real: 0m0.577s
I guess the original purpose of the question was to do this just with the shell's built-in commands. So for
loops and printf
s 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 \/\/\/\/\/\/\/\/\/\/\/\/
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 echo
s 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.
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.
A more elegant alternative to the proposed Python solution could be:
python -c 'print "="*(1000)'
Simplest is to use this one-liner in csh/tcsh:
printf "%50s\n" '' | tr '[:blank:]' '[=]'
repeat() {
# $1=number of patterns to repeat
# $2=pattern
printf -v "TEMP" '%*s' "$1"
echo ${TEMP// /$2}
}
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.
Another option is to use GNU seq and remove all numbers and newlines it generates:
seq -f'#%.0f' 100 | tr -d '\n0123456789'
This command prints the #
character 100 times.
Not to pile-on, but another pure-Bash approach takes advantage of ${//}
substitution of arrays:
$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================
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========
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
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.
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}
}
Simplest is to use this one-liner in bash:
seq 10 | xargs -n 1 | xargs -I {} echo -n ===\>;echo
Most existing solutions all depend on {1..10}
syntax support of the shell, which is bash
- and zsh
- specific, and doesn't work in tcsh
or OpenBSD's ksh
and most non-bash sh
.
The following should work on OS X and all *BSD systems in any shell; in fact, it can be used to generate a whole matrix of various types of decorative space:
$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$
Sadly, we don't get a trailing newline; which can be fixed by an extra printf '\n'
after the fold:
$ printf "=%.0s" `jot 64` | fold -16 ; printf "\n"
================
================
================
================
$
References:
My proposal (accepting variable values for n):
n=100
seq 1 $n | xargs -I {} printf =
Slightly longer version, but if you have to use pure Bash for some reason, you can use a while loop with an incrementing variable:
n=0; while [ $n -lt 100 ]; do n=$((n+1)); echo -n '='; done
here's an awk
-based repeater that's
fully POSIX-complaint
,variable-length-friendly
,completely
loop-less (in fact, doesn't even have to spend time calculating the desired length unless you wanna customize it)
, and
non-awk-variant specific
::.
jot 15 | mawk2 'NF += OFS = $_'
11
222
3333
44444
555555
6666666
77777777
888888888
9999999999
1010101010101010101010
111111111111111111111111
12121212121212121212121212
1313131313131313131313131313
141414141414141414141414141414
15151515151515151515151515151515
or just repeat the last one :
jot - 1 25 3 |
mawk2 'NF=NR^(OFS=$NF)^_' FS=
1
44
777
10000
133333
1666666
19999999
222222222
2555555555
…… or repeat ASCII punctuation
symbols with a curvature ?
jot -c - 34 126 | gtr -cd '[:punct:]\n' |
nonEmpty | rs -C'8' 0 2 |gtr -d '8' |
mawk2 'NF+=_*(OFS=__=$NF)+int(NR*(1+sin(log(NR))))' FS='^$'
"#"#
$%$%$%$%
&'&'&'&'&'&'
()()()()()()()()
*+*+*+*+*+*+*+*+*+*+
,-,-,-,-,-,-,-,-,-,-,-,-
././././././././././././././
:;:;:;:;:;:;:;:;:;:;:;:;:;:;:;
<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=
>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?
@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[
\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]
^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_
`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{
|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}
~~~~~~~~~~~~~~~~~~~~~~
or perhaps make horizontal bar charts that resemble the normal distribution :
jot -c - 34 126 | gtr -cd '0-9A-F\n' |
mawk2 'NF && (NF+=_*(OFS=$NF)+exp(cos(NR/atan2(0,-1)))^4.1)' FS='^$'
00
11111
22222222222222
333333333333333333333333333333333
444444444444444444444444444444444444444444444444444444
555555555555555555555555555555555555555555555555555555555555
66666666666666666666666666666666666666666666
7777777777777777777777
888888888
999
A
B
C
DD
EEEEEEE
FFFFFFFFFFFFFFFFFF
… if you're a gambler at heart and wanna have it repeat something related to euler e^pi
but also includes randomization, then
jot 20 |
mawk2 'NF=NR+_*(OFS=sprintf("%.f",((NR*rand()*4))*exp(atan2(0,-1))))'
|
1
2111
35252
4220220220
5177177177177
6405405405405405
7543543543543543543
8649649649649649649649
9503503503503503503503503
10555555555555555555
11669669669669669669669669669669
12110110110110110110110110110110110
13917917917917917917917917917917917917
141188118811881188118811881188118811881188118811881188
1510151015101510151015101510151015101510151015101510151015
16521521521521521521521521521521521521521521521
17900900900900900900900900900900900900900900900900
1866666666666666666
19159159159159159159159159159159159159159159159159159159
20182182182182182182182182182182182182182182182182182182182
…. or straight up letters repeating based on something that's correlated with golden ratio but not the same :
jot -c - 34 126 | gtr -cd 'A-Za-z\n' |shuf | shuf |
rs -t -C= 0 3 | gtr -d '=' |
mawk2 'NF && (NF=NR^(exp(1)/(1+sqrt(5)))+_*(OFS=$_ ($_=_)))' FS='^$'
|
qfd
NUONUO
WEvWEv
sCRsCRsCR
LoVLoVLoVLoV
putputputput
SYjSYjSYjSYjSYj
XcQXcQXcQXcQXcQ
hGrhGrhGrhGrhGrhGr
IyAIyAIyAIyAIyAIyAIyA
lZalZalZalZalZalZalZa
FMJFMJFMJFMJFMJFMJFMJFMJ
mwTmwTmwTmwTmwTmwTmwTmwT
DenDenDenDenDenDenDenDenDen
PHPHPHPHPHPHPHPHPH
iziziziziziziziziziz
…..just the last letter
jot -c - 34 126 | gtr -cd 'A-Za-z\n' |shuf | shuf |
rs -t -C= 0 2 | gtr -d '=' |
mawk2 'NF && (NF=NR^(exp(1.1)/(1+sqrt(5)))+_*(OFS=$NF))' FS=
.
l
A
kii
GIII
znnnn
fFFFFF
aHHHHHH
sSSSSSS
jooooooo
pTTTTTTTT
bDDDDDDDDD
Yvvvvvvvvvv
MCCCCCCCCCC
WBBBBBBBBBBB
JXXXXXXXXXXXX
mNNNNNNNNNNNNN
deeeeeeeeeeeee
xQQQQQQQQQQQQQQ
thhhhhhhhhhhhhhh
yOOOOOOOOOOOOOOOO
Puuuuuuuuuuuuuuuu
qRRRRRRRRRRRRRRRRR
rLLLLLLLLLLLLLLLLLL
VKKKKKKKKKKKKKKKKKKK
wUUUUUUUUUUUUUUUUUUU
ZEEEEEEEEEEEEEEEEEEEE
…and last but not least, fully UTF-8
friendly, even emojis :
|
It starts to slowdown when the reps needed is above 100 million
or so, but short of that, this can be somewhat handy for essentially matching the convenience of languages with dedicated string repeat operators like python ( * )
or perl ( x )
beware though :
it's as dangerous as it is efficacious :
jot - 1 90 8 |
mawk2 '(OFS="")(NF+=\
((sqrt(NR)))^(20.5/6.0625\
)^sqrt(sqrt(log((OFS=$!!NF))^2)))' FS='^$' OFS= |
mawk -Wi -- '{ print "\t", 8*(NR)-7,
length($0),
sprintf("%.50s",$0) }'
1 2 11
9 9 999999999
17 144 17171717171717171717171717171717171717171717171717
25 954 25252525252525252525252525252525252525252525252525
33 5146 33333333333333333333333333333333333333333333333333
41 23526 41414141414141414141414141414141414141414141414141
49 94378 49494949494949494949494949494949494949494949494949
57 340432 57575757575757575757575757575757575757575757575757
65 1124212 65656565656565656565656565656565656565656565656565
73 3445508 73737373737373737373737373737373737373737373737373
81 9904644 81818181818181818181818181818181818181818181818181
89 26930222 89898989898989898989898989898989898989898989898989
It can grow really rapidly if you only change the parameters a bit.
n=5; chr='x'; chr_string='';
for (( i=0; $i<$n; i++ ))
do
chr_string=$chr_string$chr
done
echo -n "$chr_string"
Works for...
n=integer (inclusive of zero and negetive).
chr=printable and white space (space and tab).
You can do this without invoking an external command. First you prepend 0 to a 0 until it counts a len of 100, then you replace zero with the character you want.
LEN=100
foo="$(builtin printf "%0${LEN}d" 0)"
echo "${foo//0/=}"
printf -- '=%.0s' {1..100}
The double dash --
means "End of command line flags", so don't try to parse what comes after command line options.
If you want to print the dash -
character, rather than the =
character, multiple times and don't include the double dash --
this is what you'll get:
$ printf '-%.0s' {1..100}
bash: printf: -%: invalid option
printf: usage: printf [-v var] format [arguments]
Why not create a one line function like this:
function repeat() { num="${2:-100}"; printf -- "$1%.0s" $(seq 1 $num); }
Then, you can call it like this:
$ repeat -
----------------------------------------------------------------------------------------------------
or like that:
$ repeat =
====================================================================================================
or like this:
$ repeat '*' 8
********