Answers:
更新了答案,成为更通用的解决方案。另请参阅下面的另一个答案,仅使用shell括号扩展和pritnf
。
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
怎么运行的?
这会(=*):$/
捕获一个空格,一个或多个空格,=
然后:
在输入末尾加一个冒号;我们将=
一组作为一组匹配,\1
并将其作为后向引用。
随着:loop
我们定义了一个名为标签loop
与t loop
它会跳到当该标签s/ (=*):$/\1=:/
做了成功的替换;
在替换中\1=:
,它将始终增加=
s 的数量,并将冒号本身返回到字符串的末尾。
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
给
foo=================
${#string}
是值的长度$string
,并且${filler:${#string}}
是$filler
from offset ${#string}
开始的子字符串。
输出的总宽度将等于$filler
或的最大宽度$string
。
填充字符串可以在具有的系统上jot
使用来动态创建
filler=$( jot -s '' -c 16 '=' '=' )
(=
一行中有16 个)。GNU系统可以使用seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
其他系统可能会使用Perl或其他更快的方式动态创建字符串。
printf
生成几乎在所有系统中都可用的过滤器以及带有类似shell的括号扩展bash/szh
?
printf
+大括号扩展来实现bash
?
一种方法是:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world
,如果OP需要存储它而不仅仅是将其打印到屏幕上,则可能会出现问题。
echo -e '=================\rHello World!!'
,但与@terdon指出的问题相同。
echo
支持-e
。 由于许多原因,printf
几乎总是比更好echo
。
Perl方法:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
或者,更好的是,@ SatoKatsura在评论中指出:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
如果需要支持UTF多字节字符,请使用:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
外壳中的想法相同:
v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
。但是,如果涉及多字节字符,则此方法(以及到目前为止发布的所有其他解决方案)会中断。
perl6
即使使用多字节字符,也可能有一种正确的方法。但另一方面,perl6
它在很多方面都令人讨厌。
PERL_UNICODE='AS'
。例如:printf '%s' nóóös | perl -nle 'print length($_)'
打印8(“错误”),而printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
打印5(“正确”)。
另一种方法是只使用printf
第一个命令,并生成字符填充图案的Shell Brace Expansion
(你可以把结束与一些≥格式化要打印的区域{1..end}
),并只得到它的每一个第一个字符%.1s
是=
秒,然后只打印前20个字符长度那个区域%.20s
。这是重复字符/单词而不是复制它们的更好方法。
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
说明:
通常以Brace Expansion表示,{1..20}
如果我们打印它们,则shell扩展如下。
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
因此,在其上添加等号后={1..20}
,shell将如下扩展。
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
而随着printf '%.1s'
这实际上是手段printf '%WIDE.LENGTH'
,我们仅打印一个长度在以上这些默认的1
宽。因此只会产生=
s,并且自身会重复20次。
现在,printf '%.20s:\n'
我们仅打印20的长度,$str
如果长度$str
<20,则其余部分将从生成的=
s中填充而不是空格。