我如何使用echo
?
perl -E 'say "=" x 100'
答案 0 :(得分:326)
您可以使用:
printf '=%.0s' {1..100}
这是如何运作的:
Bash扩展{1..100},命令变为:
printf '=%.0s' 1 2 3 4 ... 100
我已经将printf的格式设置为=%.0s
,这意味着无论给出什么参数,它都将始终打印一个=
。因此它会打印100 =
s。
答案 1 :(得分:79)
没有简单的方法。但是例如:
seq -s= 100|tr -d '[:digit:]'
或许是符合标准的方式:
printf %100s |tr " " "="
还有一个tput rep
,但对于我手边的终端(xterm和linux),它们似乎不支持它:)
答案 2 :(得分:39)
有多种方法可以做到这一点。
使用循环:
支撑扩展可以与整数文字一起使用:
for i in {1..100}; do echo -n =; done
类似C的循环允许使用变量:
start=1
end=100
for ((i=$start; i<=$end; i++)); do echo -n =; done
使用printf
内置:
printf '=%.0s' {1..100}
此处指定精度会截断字符串以适合指定的宽度(0
)。由于printf
重用格式字符串来使用所有参数,因此只需打印"="
100次。
使用head
(printf
等)和tr
:
head -c 100 < /dev/zero | tr '\0' '='
printf %100s | tr " " "="
答案 3 :(得分:38)
向@ gniourf_gniourf提示他的输入。
注意:此答案不回答原始问题,但 通过比较效果补充现有的有用答案。< /强>
只在执行速度方面比较 - 内存要求不被考虑在内(它们在各种解决方案中各不相同,并且可能与大量重复计数有关)。
<强>要点:强>
${var// /=}
),因为它非常慢。以下是2012年末iMac采用3.2 GHz Intel Core i5 CPU和Fusion Drive的时序,运行OSX 10.10.4和bash 3.2.57,平均值为1000次运行。
条目是:
M
...潜在的多 - 字符解决方案S
... 单 - 仅字符解决方案P
...符合POSIX标准的解决方案[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
和perl
解决方案。[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// /=}
)在使用大字符串时令人费解地极其缓慢,并且已经被淘汰(在Bash 4.3.30中花了大约50分钟(!),并且在Bash 3.2.57中更长 - 我从不等待它完成。)(( i= 0; ... ))
)比大括号扩展({1..n}
)慢 - 尽管算术循环的内存效率更高。awk
指的是 BSD awk
(也可以在OSX上找到) - 它明显慢于gawk
(GNU Awk),特别是mawk
。以下是产生上述内容的 Bash脚本(testrepeat
)。
这需要2个参数:
换句话说:上述时间是通过testrepeat 100 1000
和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
答案 4 :(得分:28)
我刚刚使用seq找到了一种非常简单的方法:
更新:这适用于OS X附带的BSD seq
。带有其他版本的YMMV
seq -f "#" -s '' 10
将打印&#39;#&#39; 10次,像这样:
##########
-f "#"
设置格式字符串以忽略这些数字,并为每个数字打印#
。-s ''
将分隔符设置为空字符串,以删除seq在每个数字之间插入的换行符-f
和-s
之后的空格似乎很重要。编辑:这是一个方便的功能......
repeat () {
seq -f $1 -s '' $2; echo
}
你可以这样打电话......
repeat "#" 10
注意:如果您重复#
,那么引号很重要!
答案 5 :(得分:17)
以下是两种有趣的方式:
ubuntu@ubuntu:~$ yes = | head -10 | paste -s -d '' - ========== ubuntu@ubuntu:~$ yes = | head -10 | tr -d "\n" ==========ubuntu@ubuntu:~$
请注意,这两者略有不同 - paste
方法以新行结尾。 tr
方法没有。
答案 6 :(得分:11)
没有简单的方法。使用printf
和替换来避免循环。
str=$(printf "%40s")
echo ${str// /rep}
# echoes "rep" 40 times.
答案 7 :(得分:7)
这是我用来在linux屏幕上打印一行字符的方法(基于终端/屏幕宽度)
printf '=%.0s' $(seq 1 $(tput cols))
说明:
按照给定的顺序打印等号多次:
printf '=%.0s' #sequence
使用命令的输出(这是一种称为Command Substitution的bash功能):
$(example_command)
给出一个序列,我以1到20为例。在最后一个命令中,使用tput命令而不是20:
seq 1 20
给出终端当前使用的列数:
tput cols
答案 8 :(得分:7)
#!/usr/bin/awk -f
BEGIN {
OFS = "="
NF = 100
print
}
或者
#!/usr/bin/awk -f
BEGIN {
while (z++ < 100) printf "="
}
答案 9 :(得分:5)
如果您希望echo
和printf
的不同实施和/或bash
以外的其他实施符合POSIX兼容性和一致性:
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'
相同的输出。
答案 10 :(得分:4)
我想问题的最初目的是使用shell的内置命令来完成这个任务。因此for
循环和printf
s是合法的,而rep
,perl
以及jot
则不合法。仍然是以下命令
jot -s "/" -b "\\" $((COLUMNS/2))
打印一个窗口范围的\/\/\/\/\/\/\/\/\/\/\/\/
答案 11 :(得分:4)
正如其他人所说,在bash brace expansion之前parameter expansion,所以{m,n}
范围只能包含文字。 seq
和jot
提供了干净的解决方案,但即使您在每个系统上使用相同的shell,也无法从一个系统完全移植到另一个系统。 (虽然seq
越来越多可用;例如,in FreeBSD 9.3 and higher。)eval
和其他形式的间接总是有效,但有点不优雅。
幸运的是,bash supports C-style for loops(仅限算术表达式)。所以这里是一个简洁的纯粹的bash&#34;方式:
repecho() { for ((i=0; i<$1; ++i)); do echo -n "$2"; done; echo; }
这将重复次数作为第一个参数,将重复的字符串(可能是单个字符,如问题描述中)作为第二个参数。 repecho 7 b
输出bbbbbbb
(以换行符结尾)。
Dennis Williamson将essentially this solution four years ago in his excellent answer提交给Creating string of repeated characters in shell script。我的函数体与那里的代码略有不同:
由于此处的重点是重复单个字符而shell是bash,因此使用echo
代替printf
可能是安全的。我在这个问题中阅读了问题描述,表达了使用echo
进行打印的偏好。上面的函数定义适用于bash和ksh93。虽然printf
更具可移植性(并且通常应该用于此类事情),但echo
的语法可以说更具可读性。
有些贝壳&#39; echo
内置函数将-
本身解释为一个选项 - 即使使用stdin作为输入的-
的通常含义,对echo
也没有意义。 zsh这样做。肯定存在echo
,不能识别-n
,it is not standard。 (许多Bourne风格的贝壳根本不接受C风格的循环,因此不需要考虑他们的echo
行为。)
这里的任务是打印序列; there,是将其分配给变量。
如果$n
是所需的重复次数而您不必重复使用,并且您想要更短的内容:
while ((n--)); do echo -n "$s"; done; echo
n
必须是变量 - 这种方式不适用于位置参数。 $s
是要重复的文字。
答案 12 :(得分:3)
纯粹的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
中。printf
将使用该参数打印相应数量的空格。例如,printf '%*s' 42
将打印42个空格。${var// /$pattern}
将扩展为var
的扩展所有空格被$pattern
的扩展所取代。您还可以使用间接扩展删除tmp
函数中的repeat
变量:
repeat() {
# $1=number of patterns to repeat
# $2=pattern
# $3=output variable name
printf -v "$3" '%*s' "$1"
printf -v "$3" '%s' "${!3// /$2}"
}
答案 13 :(得分:2)
for i in {1..100}
do
echo -n '='
done
echo
答案 14 :(得分:2)
问题在于如何使用echo
:
echo -e ''$_{1..100}'\b='
这将与perl -E 'say "=" x 100'
完全相同,但仅使用echo
。
答案 15 :(得分:2)
Python无处不在,无处不在。
TeachersData[TeachersData$Teacher_ID==input$Selecter,]
字符和计数作为单独的参数传递。
答案 16 :(得分:2)
repeat() {
# $1=number of patterns to repeat
# $2=pattern
printf -v "TEMP" '%*s' "$1"
echo ${TEMP// /$2}
}
答案 17 :(得分:2)
在bash 3.0或更高版本中
for i in {1..100};do echo -n =;done
答案 18 :(得分:1)
这是Eliah Kagan所支持的更长版本:
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为初始数字。
答案 19 :(得分:1)
如果你想重复一个字符n次是一个VARIABLE次数,这取决于你可以做的字符串的长度:
#!/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========
答案 20 :(得分:1)
我该如何用echo做到这一点?
可以用做echo
,如果echo
后跟sed
:
echo | sed -r ':a s/^(.*)$/=\1/; /^={100}$/q; ba'
实际上,在那里echo
是不必要的。
答案 21 :(得分:1)
不要堆积,而是另一种纯Bash方法利用数组的${//}
替换:
$ arr=({1..100})
$ printf '%s' "${arr[@]/*/=}"
====================================================================================================
答案 22 :(得分:0)
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
********
答案 23 :(得分:0)
版本稍长,但是如果由于某些原因必须使用纯Bash,则可以使用带有递增变量的while循环:
length[j]
答案 24 :(得分:0)
我的提案(接受n的变量值)
~4.5.0
答案 25 :(得分:0)
另一个意思是将任意字符串重复n次:
优点:
缺点:
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序列。repeat_char
ANSI CSI序列扩展为重复的字符。答案 26 :(得分:0)
大多数现有解决方案都依赖于{1..10}
和bash
特定的Shell语法支持,并且不适用于zsh
或OpenBSD的ksh
和大多数非流行tcsh
。
以下内容应在OS X和任何外壳中的所有* BSD系统上运行;实际上,它可以用于生成各种类型的装饰空间的整个矩阵:
sh
遗憾的是,我们没有尾随换行符;折叠后可以通过额外的$ printf '=%.0s' `jot 64` | fold -16
================
================
================
================$
进行固定:
printf '\n'
参考文献:
答案 27 :(得分:0)
另一种选择是使用GNU seq并删除其生成的所有数字和换行符:
seq -f'#%.0f' 100 | tr -d '\n0123456789'
此命令将#
字符打印100次。
答案 28 :(得分:0)
一个比拟议的Python解决方案更优雅的替代方案可能是:
python -c 'print "="*(1000)'
答案 29 :(得分:0)
最简单的方法是在bash中使用这种单线:
seq 10 | xargs -n 1 | xargs -I {} echo -n ===\>;echo
答案 30 :(得分:0)
我的回答比较复杂,可能还不完美,但是对于那些希望输出大量数字的人来说,我能够在3秒钟内完成约一千万次操作。
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}
}
答案 31 :(得分:0)
最简单的方法是在csh / tcsh中使用这种单行代码:
printf "%50s\n" '' | tr '[:blank:]' '[=]'
答案 32 :(得分: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
}
样品运行
$ repeatString 'a1' 10
a1a1a1a1a1a1a1a1a1a1
$ repeatString 'a1' 0
$ repeatString '' 10
参考资料库:https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash
答案 33 :(得分:-1)
n=5; chr='x'; chr_string='';
for (( i=0; $i<$n; i++ ))
do
chr_string=$chr_string$chr
done
echo -n "$chr_string"
适用于...
n =整数(包括零和整数)。
chr =可打印的空白(空格和制表符)。