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}}是$fillerfrom 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中填充而不是空格。