文字列の末尾の空白を別の文字で埋める


12

hello world20文字以上出力したいです。

printf "%-20s :\n\n" 'hello world!!'

# Actual output
hello world!!        :

# Wanted output
hello world!!========:

ただし、スペースで補完するのではなく、代わりに「=」で補完します。それ、どうやったら出来るの?

回答:


9

より一般的なソリューションになるように回答を更新しました。また、参照して以下の私の別の答えだけのシェルブレース展開を使用するとpritnf

$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:

使い方?

これは、入力の最後にコロンが続く(=*):$/1つ以上のスペースを1つキャプチャします。のセットをグループ一致として作成し、その後方参照になります。=:=\1

では:loop、私たちは、名前のラベルを定義したloopとしてt loopたときに、それはそのラベルにジャンプしますs/ (=*):$/\1=:/成功した置換を行っています。

で置き換える部分では\1=:、常に=s の数を増やし、コロン自体を文字列の最後に戻します。


1
入力に含まれる単語の数に応じてフラグを調整する必要がありますか?
user1686

@grawity一般的な解決策に対する回答を更新しました。
αғsнιη

20
filler='===================='
string='foo'

printf '%s\n' "$string${filler:${#string}}"

与える

foo=================

${#string}値の長さであり$string、そして${filler:${#string}}のサブストリングである$fillerオフセットから${#string}以降。

出力の合計幅は、$fillerまたはの最大幅の幅になり$stringます。

フィラー文字列は、 jot、次を使用して動的に作成できます。

filler=$( jot -s '' -c 16 '=' '=' )

(16 =行で)。GNUシステムはseq

filler=$( seq -s '=' 1 16 | tr -dc '=' )

他のシステムでは、Perlまたは文字列を動的に作成する他の高速な方法を使用する場合があります。


なぜprintfすべてのシステムでほとんど利用できるフィルターを生成するために使用しないのbash/szhですか?
αғsнιη

@sddgob printf+ブレース展開でそれをどのように行いbashますか?
クサラナナンダ

チェックしてくださいunix.stackexchange.com/a/399059/72456
αғsнιη

17
printf "%.20s:\n\n" "$str========================="

ここ%.20sで、文字列はフォーマットを切り捨てます


2
これは、私よりも優れたソリューションです。書式文字列の簡単な説明のみが必要です。
クサラナナンダ

12

それを行う1つの方法:

printf "====================:\r%s\n\n" 'hello world!!'

6
ハ!それは賢いトリックです!ただし、実際に印刷されます====================\rhello world。これは、OPが画面に印刷するだけでなく、これを保存する必要がある場合に問題になる可能性があります。
テルドン

またecho -e '=================\rHello World!!'、@terdonが指摘したのと同じ問題があります。
αғsнιη

1
@αғsнιηがechoサポートされて-eいる場合のみ。 多くの理由により、printfほとんどの場合、よりも優れechoています。
桂佐藤

5

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"'。ただし、マルチバイト文字が関係する場合、これ(およびこれまでに投稿された他のすべてのソリューション)は壊れます。
桂佐藤

@SatōKatsuraooh、はい、それはすてきです!そのことを考えておくべきだった、ありがとう。そして、はい、私はUTFマルチバイト文字で起こりうる失敗に対する免責事項を追加することを考えていましたが、このコンテキストでは不必要な複雑さになると考えました。
テルドン

perl6マルチバイト文字でも正しく行う方法があると思います。しかし、一方でperl6は非常に多くの点で迷惑です。
桂佐藤

@SatōKatsuraよく、この種の単純なことのために、設定するだけで十分でしょうPERL_UNICODE='AS'。たとえば、printf '%s' nóóös | perl -nle 'print length($_)'8(「間違った」)をprintf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'印刷し、5(「正しい」)を印刷します。
テルドン

5

もう一つの方法は、のみ使用しているprintfことで、コマンドと最初の文字のパディングパターンを生成するShell Brace Expansionあなたが置くことができます(最後のあなたが印刷する数≥フォーマットするエリアとを{1..end})、その最初の文字で%.1sある=s のみを取得し、最初の20文字の長さのみを印刷しますそのエリア%.20s。これは、文字/単語を複製するのではなく、文字/単語を繰り返すより良い方法です。

printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:

説明:

通常として Brace Expansion{1..20}それらを印刷すると、シェルは次のように展開します。

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}、シェルは次のように展開されます。

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'、我々は一つだけ印刷されているLENGTHデフォルトで上記のそれらのを1 WIDE。結果は=sのみで、20回繰り返されます。

これでprintf '%.20s:\n'、20の長さのみを印刷$strし、長さが$str20未満の場合、残りは生成された=sから取得し、スペースではなく埋めます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.