71

有没有办法在 bash 中重复打印相同的字符,就像你可以在 python 中使用这个结构一样:

print('%' * 3)

%%%
4

9 回答 9

163

实际上有一个单线可以做到这一点:

    printf "%0.s-" {1..10}

印刷

    ----------

以下是传递给的参数的细分printf

  • %s - 指定任意长度的字符串
  • %0s - 这指定一个长度为零的字符串,但如果参数更长,它将打印整个内容
  • %0.s - 这与上面相同,但printf如果字符串长于指定长度(为零),则该句点告诉截断字符串
  • {1..10} - 这是一个实际传递参数“1 2 3 4 5 6 7 8 9 10”的大括号扩展
  • “-” - 这是提供给 的额外字符printf,可以是任何字符(对于“%”,您必须先用另一个“%”转义它,即“%%”)
  • 最后,如果你给它的参数多于格式字符串中指定的参数,默认行为printf是循环回到格式字符串的开头并再次运行它。

那么这里发生的事情的最终结果是,printf如果提供的字符串长于零,则您希望它打印一个零长度的字符串,而没有多余的字符。然后在这个零长度字符串之后打印一个“-”(或任何其他字符集)。然后为它提供 10 个参数,因此它会打印 10 个零长度字符串,每个字符串后面都有一个“-”。

它是一种可以打印任意数量的重复字符的单行线!

编辑:

巧合的是,如果要打印$variable字符,只需稍微更改参数即可使用,seq而不是大括号扩展,如下所示:

    printf '%0.s-' $(seq 1 $variable)

这会将参数“1 2 3 4 ... $variable”传递给printf,精确打印$variable“-”的实例

于 2013-06-10T19:04:35.070 回答
56

当然,只需使用printf一些 bash 字符串操作

$ s=$(printf "%-30s" "*")
$ echo "${s// /*}"
******************************

应该有更短的方法,但目前我就是这样做的。你可以把它变成一个函数,你可以将它存储在一个库中以备将来使用

printf_new() {
 str=$1
 num=$2
 v=$(printf "%-${num}s" "$str")
 echo "${v// /*}"
}

测试运行:

$ printf_new "*" 20
********************
$ printf_new "*" 10
**********
$ printf_new "%" 10
%%%%%%%%%%
于 2011-04-27T04:27:51.300 回答
31

这个问题的当前接受的答案(由ghostdog74提供)提供了一种即使对于中等数量的字符也执行得非常慢的方法。投票最多的答案(由CaffeineConnoisseur提供)更好,但仍然很慢。

在我的测试中,这是执行速度最快的(甚至比 python 版本更快):

perl -E "print '*' x 1000"

排在第二位的是 python 命令:

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

如果 perl 和 python 都不可用,那么这是第三好的:

head -c 1000 /dev/zero | tr '\0' '*'

排在第四位的是使用 bashprintf内置以及tr

printf '%*s' 1000 | tr ' ' '*'

这是一个(来自CaffeineConnoisseur的回答)对于大量重复字符的速度排名第五,但对于少量重复字符可能更快(由于仅使用内置的 bash,而不是产生外部进程):

printf '%.s*' {1..1000}
于 2014-02-26T16:56:31.647 回答
13

我喜欢这个:

echo $(yes % | head -n3)

你可能不喜欢这样:

for ((i=0; i<3; i++)){
   echo -ne "%"
}

你可能会喜欢这样:

s=$( printf "%3s" ); echo " ${s// /%}"

来源:http ://dbaspot.com/shell/357767-bash-fast-way-repeat-string.html

也有这种形式,但不是很有用:

echo %{,,}
于 2011-04-27T04:24:45.530 回答
5

这很难看,但你可以这样做:

$ for a in `seq 5`; do echo -n %; done
%%%%%

当然,seq是一个外部程序(你可能有)。

于 2011-04-27T04:24:06.273 回答
3
  1. 可以从 中获取任意数量的零 ( \0) 字符/dev/zero。剩下要做的就是

    head -c 20 /dev/zero |tr '\0' '+'
    

    注意headtr是外部命令。这样它将在单独的进程中调用。

  2. 可以使用字符串缓存“优化”这个解决方案。

    CACHE="$(head -c 1000 /dev/zero |tr '\0' '+')"
    echo "${CACHE:0:10}"
    echo "${CACHE:0:100}"
    echo "${CACHE:0:300}"
    

    echo 语句中只有bash内置函数。所以,我们可以循环使用它。

于 2013-05-17T20:13:38.583 回答
2

另一个:

char='%'
count=5
result=$( printf "%${count}s" ' ' )
echo -e ${result// /$char}
于 2011-04-27T08:21:49.120 回答
1
#!/usr/bin/awk -f
BEGIN {
  while (c++ < 3) printf "%"
}

结果

%%%
于 2014-06-01T08:25:18.637 回答
0

这是最简单的方法

seq -s % 4|tr -d '[:digit:]'

请注意,创建的序列中只有 3 '%'。

于 2013-11-29T11:34:52.373 回答