Padding trailing whitespaces in a string with another character
Solution 1
Updated answer to be more general solution. see also my another answer below using only shell brace expansion and printf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
How it works?
this (=*):$/
captures one space, one-or-more =
that followed by a colon :
in the end of its input; we make the set of =
as a group match and \1
will be its back-reference.
With :loop
we defined a label named loop
and with t loop
it will jump to that label when a s/ (=*):$/\1=:/
has done successful substitution;
In replacement part with \1=:
, it will always increment the number of =
s and back the colon itself to the end of string.
Solution 2
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
Gives
foo=================
${#string}
is the length of the value $string
, and ${filler:${#string}}
is the substring of $filler
from offset ${#string}
onwards.
The total width of the output will be that of the maximum width of $filler
or $string
.
The filler string can, on systems that has jot
, be created dynamically using
filler=$( jot -s '' -c 16 '=' '=' )
(for 16 =
in a line). GNU systems may use seq
:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Other systems may use Perl or some other faster way of creating the string dynamically.
Solution 3
printf "%.20s:\n\n" "$str========================="
where %.20s
is the string truncating format
Solution 4
One way to do it:
printf "====================:\r%s\n\n" 'hello world!!'
Solution 5
A Perl approach:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
Or, better, @SatoKatsura pointed out in the comments:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
If you need to support UTF multi-byte characters, use:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Same idea in the shell:
v='hello world!!'; while [ ${#v} -lt 20 ]; do v="$v""="; done; printf '%s\n\n' "$v"
Related videos on Youtube
smarber
Updated on September 18, 2022Comments
-
smarber over 1 year
I'd like to output
hello world
over 20 characters.printf "%-20s :\n\n" 'hello world!!' # Actual output hello world!! : # Wanted output hello world!!========:
However, I don't want to complete with spaces but with "=" instead. How do I do that?
-
terdon over 6 yearsHa! That's a clever trick! However, it will actually print
====================\rhello world
, which might be an issue if the OP needs to store this and not just print it to screen. -
Satō Katsura over 6 yearsYou don't need a loop:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
. However, this (and all other solutions posted so far) breaks if multi-byte characters are involved. -
terdon over 6 years@SatōKatsura ooh, yes, that's neat! Should have thought of that, thanks. And yes, I was thinking of adding a disclaimer for possible failure on UTF multi-byte characters, but figured it would be a needless complication in this context.
-
Satō Katsura over 6 yearsI think
perl6
might have a way to do it correctly even with multi-byte characters. But on the other handperl6
is annoying in so many ways. -
terdon over 6 years@SatōKatsura well, for this sort of simple thing, it should be enough to just set
PERL_UNICODE='AS'
. For example:printf '%s' nóóös | perl -nle 'print length($_)'
prints 8 ("wrong") whileprintf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
prints 5 ("correct"). -
Kusalananda over 6 yearsThis is IMHO, a better solution than mine. It only needs a short explanation of the format string.
-
user1686 over 6 yearsso you have to adjust the flag depending on how many words the input has?
-
αғsнιη over 6 yearsalso
echo -e '=================\rHello World!!'
, but has same issue as @terdon pointed that. -
Satō Katsura over 6 years@αғsнιη Only if
echo
supports-e
.printf
is almost always better thanecho
, for many reasons. -
αғsнιη over 5 years@grawity I have updated my answer to general solution now.
-
Kusalananda over 5 years@sddgob How would you do it with
printf
+ brace expansion inbash
?