#!/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
function repeatString()
{
local -r string="${1}"
local -r numberToRepeat="${2}"
if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]]
then
local -r result="$(printf "%${numberToRepeat}s")"
echo -e "${result// /${string}}"
fi
}
repeatString(){
# 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}
}