如何在Bash中重复一个字符?

我如何用echo做到这一点?

perl -E 'say "=" x 100'
225154 次浏览

在bash 3.0或更高版本中

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

有不止一种方法。

使用循环:

  • 大括号展开可用于整型字面值:

    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}

在这里指定精度将截断字符串以适合指定的宽度(0)。由于printf重用格式字符串来使用所有参数,这只是打印"=" 100次。

使用head (printf等)和tr:

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

没有简单的方法。但是举个例子:

seq -s= 100|tr -d '[:digit:]'
# Editor's note: This requires BSD seq, and breaks with GNU seq (see comments)

或者是一种符合标准的方式:

printf %100s |tr " " "="

还有一个tput rep,但对于我手头的终端(xterm和linux),它们似乎不支持它:)

没有简单的办法。使用printf和substitution避免循环。

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

你可以使用:

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

这是如何工作的:

Bash扩展{1..100},那么命令就变成:

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

我已经将printf的格式设置为=%.0s,这意味着无论给出什么参数,它总是打印单个=。因此,它输出100个__abc1。

如果你想重复一个字符n次,n是一个变量的次数,这取决于,比如说,字符串的长度,你可以这样做:

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

它显示:

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

我猜这个问题的最初目的是仅用shell的内置命令来完成这个任务。所以for循环和__abc1循环是合法的,而下面的repperljot循环则是不合法的。但是,下面的命令

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

例如,打印窗口宽的\/\/\/\/\/\/\/\/\/\/\/\/

这里有两种有趣的方法:

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

注意这两个方法有细微的不同——paste方法以新行结束。tr方法没有。

我刚刚发现了一个非常简单的方法来做到这一点使用seq:

更新:此操作适用于OS x附带的BSD seq。YMMV与其他版本

seq  -f "#" -s '' 10

将打印'#' 10次,如下所示:

##########
  • -f "#"设置格式字符串忽略数字,只打印每个数字的#
  • -s ''将分隔符设置为空字符串,以删除seq在每个数字之间插入的换行符
  • -f-s之后的空格似乎很重要。

编辑:这里是一个方便的功能…

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

你可以这样叫它…

repeat "#" 10

如果你在重复#,那么引号很重要!

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

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

使用实例

一种纯Bash方式,没有eval,没有子shell,没有外部工具,没有大括号展开(即,你可以在变量中重复数字):

如果给你一个展开为(非负)数的变量n和一个变量pattern,例如,

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

你可以用它来创建一个函数:

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

这套:

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

对于这个小技巧,我们经常使用printf:

  • -v varname:而不是打印到标准输出,printf将格式化字符串的内容放在变量varname中。
  • '%*s': printf将使用参数打印相应的空格数。例如,printf '%*s' 42将打印42个空格。
  • 最后,当变量中有所需数量的空格时,我们使用参数展开将所有空格替换为我们的模式:${var// /$pattern}将展开为var的展开,所有空格替换为$pattern的展开。

你也可以通过间接展开来摆脱repeat函数中的tmp变量:

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

正如其他人所说,在bash中支架扩张参数扩展之前,所以{m,n}范围只能包含字面量。seqjot提供了干净的解决方案,但不能完全从一个系统移植到另一个系统,即使你在每个系统上使用相同的shell。(尽管seq越来越可用;例如,FreeBSD 9.3及更高版本.) seq0和其他形式的间接总是工作,但有点不优雅。

幸运的是,bash 支持c风格的for循环(仅使用算术表达式)。这里有一个简洁的“纯bash”方法:

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

这将重复次数作为第一个参数,将要重复的字符串(如问题描述中所示,可以是单个字符)作为第二个参数。repecho 7 b输出bbbbbbb(以换行符结束)。

丹尼斯·威廉姆森本质上这个解决方案是四年前他的精彩回答赋值给在shell脚本中创建重复字符字符串。我的函数体与代码略有不同:

  • 因为这里的重点是重复单个字符,并且shell是bash,所以使用echo而不是printf可能是安全的。我读到这个问题中的问题描述表达了用echo打印的偏好。上面的函数定义适用于bash和ksh93。虽然printf更可移植(通常应该用于这类事情),但echo的语法可以说更可读。

    一些shell的echo内置程序将-本身解释为一个选项——尽管-的通常含义,即使用stdin作为输入,对于echo来说是毫无意义的。zsh做到这一点。而且肯定存在__abc0不能将-n识别为不标准。(许多bourne风格的shell根本不接受c风格的for循环,因此不需要考虑它们的echo行为..)

  • 这里的任务是打印序列;there,它被赋值给一个变量。

如果$n是期望的重复次数,并且你不需要重用它,并且你想要更短的内容:

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

n必须是一个变量——这种方法不适用于位置参数。$s是要重复的文本。

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

如果你想要在echoprintf的不同实现之间遵循posix并保持一致性,和/或除了bash之外的shell:

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


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

...将在几乎所有地方产生与perl -E 'say "=" x 100'相同的输出。

这是以利亚·卡根所支持的观点的长版本:

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

当然,你也可以使用printf,但不是我喜欢的:

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

这个版本与Dash兼容:

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

I是初始数。

向@gniourf_gniourf表示敬意。

注意:这个答案回答了原来的问题,但是补充现有的有用答案,通过比较性能 . 0回答了原来的问题

解决方案是仅在执行速度方面进行比较——内存需求被考虑在内(它们在不同的解决方案中有所不同,并且可能与大量重复计数有关)。

简介:

    如果你的重复计数small高达100左右,它就是值得使用Bash-only解决方案,因为外部实用程序的启动成本很重要,尤其是Perl的。
    • 然而,从实用主义的角度来说,如果你只需要重复字符的一个实例,所有现有的解决方案可能都是好的。
    • 李< / ul > < / >
    • 使用large repeat counts使用外部工具,因为它们会更快。
        特别地,避免Bash的全局子字符串替换为大字符串
        (例如,${var// /=}),因为它非常慢 李< / ul > < / >

      下面的计时是在2012年末的iMac上进行的,使用3.2 GHz英特尔酷睿i5 CPU和Fusion Drive,运行OSX 10.10.4和bash 3.2.57,并且是1000次运行的平均值。

      条目如下:

      • 按执行时间升序列出(最快的先)
      • <李>前缀:
        • M……一个潜在的-character解决方案
        • S……一个-character-only解决方案
        • P……posix兼容的解决方案
        • 李< / ul > < / >
        • 接下来是对解决方案的简要描述
        • 以原始答案的作者的名字作为后缀

        • 小重复计数:100
        [M, P] printf %.s= [dogbane]:                           0.0002
        [M   ] printf + bash global substr. replacement [Tim]:  0.0005
        [M   ] echo -n - brace expansion loop [eugene y]:       0.0007
        [M   ] echo -n - arithmetic loop [Eliah Kagan]:         0.0013
        [M   ] seq -f [Sam Salisbury]:                          0.0016
        [M   ] jot -b [Stefan Ludwig]:                          0.0016
        [M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.0019
        [M, P] awk - while loop [Steven Penny]:                 0.0019
        [S   ] printf + tr [user332325]:                        0.0021
        [S   ] head + tr [eugene y]:                            0.0021
        [S, P] dd + tr [mklement0]:                             0.0021
        [M   ] printf + sed [user332325 (comment)]:             0.0021
        [M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0025
        [M, P] mawk - while loop [Steven Penny]:                0.0026
        [M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0028
        [M, P] gawk - while loop [Steven Penny]:                0.0028
        [M   ] yes + head + tr [Digital Trauma]:                0.0029
        [M   ] Perl [sid_com]:                                  0.0059
        
        • 只有bash的解决方案领先的包-但只有重复计数这么小!(见下文)。
        • 外部实用程序的启动成本在这里很重要,特别是Perl的启动成本。如果你必须在循环中调用它——每次迭代中都有重复计数——避免使用multiutility、awkperl解决方案。

        • 大重复计数:1000000(100万)
        [M   ] Perl [sid_com]:                                  0.0067
        [M   ] mawk - $(count+1)="=" [Steven Penny (variant)]:  0.0254
        [M   ] gawk - $(count+1)="=" [Steven Penny (variant)]:  0.0599
        [S   ] head + tr [eugene y]:                            0.1143
        [S, P] dd + tr [mklement0]:                             0.1144
        [S   ] printf + tr [user332325]:                        0.1164
        [M, P] mawk - while loop [Steven Penny]:                0.1434
        [M   ] seq -f [Sam Salisbury]:                          0.1452
        [M   ] jot -b [Stefan Ludwig]:                          0.1690
        [M   ] printf + sed [user332325 (comment)]:             0.1735
        [M   ] yes + head + tr [Digital Trauma]:                0.1883
        [M, P] gawk - while loop [Steven Penny]:                0.2493
        [M   ] awk - $(count+1)="=" [Steven Penny (variant)]:   0.2614
        [M, P] awk - while loop [Steven Penny]:                 0.3211
        [M, P] printf %.s= [dogbane]:                           2.4565
        [M   ] echo -n - brace expansion loop [eugene y]:       7.5877
        [M   ] echo -n - arithmetic loop [Eliah Kagan]:         13.5426
        [M   ] printf + bash global substr. replacement [Tim]:  n/a
        
        • 这个问题的Perl解决方案是目前为止最快的。
        • Bash的全局字符串替换(${foo// /=})对于大字符串来说速度慢得令人费解,并且已经被淘汰(在Bash 4.3.30中大约花了50分钟(!),在Bash 3.2.57中甚至更久——我从来没有等待它完成)。
        • Bash循环很慢,算术循环((( i= 0; ... )))比大括号扩展的循环({1..n})慢——尽管算术循环更节省内存。
        • awk指的是BSD awk(在OSX上也可以找到)——它明显比gawk (GNU Awk)慢,尤其是mawk
        • 注意,对于大的计数和多字符。字符串,内存消耗可以成为一个考虑因素-方法在这方面有所不同。

        这里是产生上述结果的Bash脚本 (testrepeat)。 它有两个参数:

        • 字符重复计数
        • 可选地,要执行和计算平均计时的测试运行的数量

        换句话说:上面的计时是用testrepeat 100 1000testrepeat 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
        

Python无处不在,在任何地方都能正常工作。

< p > <代码> import sys;Print ('*' * int(sys.argv[1]))"" = " 100 < /代码> < / p >

Character和count作为单独的参数传递。

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


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

样本运行

$ repeatString 'a1' 10
a1a1a1a1a1a1a1a1a1a1


$ repeatString 'a1' 0


$ repeatString '' 10

引用库位于:https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

最简单的方法是在csh/tcsh中使用这一行代码:

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

问题是关于如何使用echo:

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

这将与perl -E 'say "=" x 100'完全相同,但只使用echo

我怎么用echo来做呢?

如果echo后面跟着sed,则可以使用echo:

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

实际上,echo在这里是不必要的。

我的答案有点复杂,可能并不完美,但对于那些希望输出大数字的人来说,我能够在3秒内完成大约1000万。

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

最简单的方法是在bash中使用这一行代码:

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

建议的Python解决方案的更优雅的替代方案可能是:

python -c 'print "="*(1000)'

另一种选择是使用GNU seq并删除它生成的所有数字和换行:

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

这个命令打印100次#字符。

大多数现有的解决方案都依赖于shell的{1..10}语法支持,这是bashzsh特定的,并且在tcsh或OpenBSD的ksh和大多数非bash的sh中不起作用。

以下代码适用于OS X和所有*BSD系统;实际上,它可以用来生成各种类型装饰空间的整体矩阵:

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

遗憾的是,我们没有得到一个尾随换行符;这可以在折叠后通过额外的printf '\n'来修复:

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

引用:

  • < a href = " http://mdoc.su/-/printf。1" rel="nofollow noreferrer">http://mdoc.su/-/printf.1 .
  • < a href = " http://mdoc.su/-/jot。1" rel="nofollow noreferrer">http://mdoc.su/-/jot.1 .
  • < a href = " http://mdoc.su/-/fold。1" rel="nofollow noreferrer">http://mdoc.su/-/fold.1 .

另一种表示任意字符串重复n次:

优点:

  • 使用POSIX shell工作。
  • 输出可以赋值给一个变量。
  • 重复任何字符串。
  • 即使有很大的重复也非常快。

缺点:

  • 需要Gnu Core Utils的yes命令。
#!/usr/bin/sh
to_repeat='='
repeat_count=80
yes "$to_repeat" | tr -d '\n' | head -c "$repeat_count"

使用ANSI终端和重复的US-ASCII字符。您可以使用ANSI CSI转义序列。这是重复一个汉字最快的方法。

#!/usr/bin/env bash


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

或静态:

打印80行=:

printf '=\e[80b\n'

限制:

  • 不是所有的终端都理解repeat_char ANSI CSI序列。
  • 只能重复US-ASCII或单字节ISO字符。
  • 在最后一列重复停止,因此可以使用较大的值来填充整行,而不管终端宽度如何。
  • 重复只是为了显示。将输出捕获到shell变量中不会将repeat_char ANSI CSI序列扩展为重复字符。

下面是我在linux中用来在屏幕上打印一行字符的方法(基于终端/屏幕宽度)

打印“=”;屏幕对面:

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

解释:

打印等号的次数与给定序列相同:

printf '=%.0s' #sequence

使用命令的输出(这是bash的一个叫做命令替换的特性):

$(example_command)

给出一个序列,我以1到20为例。在最后一个命令中,使用tput命令代替20:

seq 1 20

给出终端中当前使用的列数:

tput cols

我的建议(接受n的变量值):

n=100
seq 1 $n | xargs -I {} printf =

不是堆砌,而是另一种纯bash方法利用${//}替换数组:

$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================
n=5; chr='x'; chr_string='';
for (( i=0; $i<$n; i++ ))
do
chr_string=$chr_string$chr
done
echo -n "$chr_string"
< p >工作……
N =整数(包括0和负数)。
Chr =可打印和空白(空格和制表符).

稍微长一点的版本,但如果你出于某种原因必须使用纯Bash,你可以使用一个带增量变量的while循环:

n=0; while [ $n -lt 100 ]; do n=$((n+1)); echo -n '='; done
printf -- '=%.0s' {1..100}

双破折号--表示“命令行标志的结束”,所以不要试图解析命令行选项后面的内容。

如果你想打印破折号-字符,而不是=字符,多次并且不包括双破折号--,这是你会得到的:

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

为什么不创建这样的一行函数呢:

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

然后,你可以这样调用它:

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

或者像这样:

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

或者像这样:

$ repeat '*' 8
********

另一个使用printf和tr的bash解决方案

nb。在开始之前:

  • 我们需要另一个答案吗?可能不会。
  • 答案已经在这里了吗?看不见,就这样。

使用printf的前导零填充特性,并使用tr转换零。这避免了任何{1..N}生成器:

$ printf '%040s' | tr '0' '='
========================================

设置宽度为'N'字符,并自定义打印的字符:

#!/usr/bin/env bash
N=40
C='-'
printf "%0${N}s" | tr '0' "${C}"

对于大N,这比生成器的性能要好得多;在我的机器上(bash 3.2.57):

$ time printf '=%.0s' {1..1000000}         real: 0m2.580s
$ time printf '%01000000s' | tr '0' '='    real: 0m0.577s

这是一个基于__abc0的中继器

  • fully POSIX-complaint,
  • variable-length-friendly,

完全 loop-less (in fact, doesn't even have to spend time calculating the desired length unless you wanna customize it),和

  • non-awk-variant specific::

jot 15 | mawk2 'NF += OFS = $_'


11
222
3333
44444
555555
6666666
77777777
888888888
9999999999
1010101010101010101010
111111111111111111111111
12121212121212121212121212
1313131313131313131313131313
141414141414141414141414141414
15151515151515151515151515151515

或者只是重复最后一个:

jot - 1 25 3 |


mawk2 'NF=NR^(OFS=$NF)^_' FS=


1
44
777
10000
133333
1666666
19999999
222222222
2555555555

......或重复带有曲率的ASCII punctuation符号?

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='^$'


"#"#
$%$%$%$%
&'&'&'&'&'&'
()()()()()()()()
*+*+*+*+*+*+*+*+*+*+
,-,-,-,-,-,-,-,-,-,-,-,-
././././././././././././././
:;:;:;:;:;:;:;:;:;:;:;:;:;:;:;
<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=<=
>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?>?
@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[@[
\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]\]
^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_^_
`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{`{
|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}|}
~~~~~~~~~~~~~~~~~~~~~~

或者可以制作类似正态分布的水平柱状图:

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

…如果你内心是一个赌徒,想让它重复一些与euler e^pi相关的东西,但也包括随机化,那么

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

.... 或者直接的字母重复,基于与黄金比例相关但不相同的东西:

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

…就最后一封信

 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

…最后但并非最不重要的是,完全UTF-8友好,甚至是表情符号: | < / p >

😪 😪
😫 😫 😫
😬 😬 😬 😬
😭 😭 😭 😭 😭

当所需的代表数超过100 million左右时,它开始变慢,但如果没有,这在本质上可以很方便地匹配语言的便便性,例如python ( * )perl ( x )

不过要注意: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

如果你只改变一点参数,它可以快速增长真的<强> < / >强

使用grep的非正统但有趣的解决方案

grep -zom100 ^= /dev/random