Yanıtlar:
Daha genel bir çözüm olması için cevap güncellendi. ayrıca sadece kabuk ayracı genişletme ve kullanarak başka bir cevap bakınpritnf .
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Nasıl çalışır?
bu , girdisinin sonunda bir iki nokta üst üste izleyen bir (=*):$/veya daha fazla boşluk yakalar ; grup eşleşmesi olarak set yaparız ve geri referansı oluruz .=:=\1
İle :loopbiz bir etiket adında tanımlanır loopve birlikte t loopbir o etikete atlar s/ (=*):$/\1=:/başarılı ikame çıkarmış;
Yedek parça ile \1=:her zaman =s sayısını artıracak ve kolonun kendisini ipin sonuna kadar geri getirecektir.
filler='===================='
string='foo'
printf '%s\n' "$string${filler:${#string}}"
verir
foo=================
${#string}değerin uzunluğu $stringve ofsetten itibaren ${filler:${#string}}alt dizisidir.$filler${#string}
Çıktının toplam genişliği $fillerveya genişliğinin maksimum genişliği olacaktır $string.
Dolgu dizesi, jotdinamik olarak oluşturulmuş sistemlerde
filler=$( jot -s '' -c 16 '=' '=' )
( =bir satırda 16 için ). GNU sistemleri şunları kullanabilir seq:
filler=$( seq -s '=' 1 16 | tr -dc '=' )
Diğer sistemler Perl'i veya dizeyi dinamik olarak oluşturmanın daha hızlı bir yolunu kullanabilir.
printf+ ayraç genişletmesi ile nasıl yaparsınız bash?
printf "%.20s:\n\n" "$str========================="
%.20sdize kesme biçimi nerede
Bunu yapmanın bir yolu:
printf "====================:\r%s\n\n" 'hello world!!'
====================\rhello world, bu da OP'nin bunu sadece ekrana yazdırmakla kalmaması için saklaması gerekiyorsa bir sorun olabilir.
echo -e '=================\rHello World!!', @terdon ile aynı konuya işaret etti.
echodestekliyorsa -e. birçok nedenden ötürü printfneredeyse her zaman daha iyidir echo.
Bir Perl yaklaşımı:
$ perl -le '$k="hello world!!"; while(length($k)<20){$k.="=";} print "$k\n"'
hello world!!=======
Ya da, daha iyi, @SatoKatsura yorumlarda dikkat çekti:
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
UTF çok baytlı karakterleri desteklemeniz gerekiyorsa, şunları kullanın:
PERL_UNICODE='AS' perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
Kabuktaki aynı fikir:
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"'. Ancak, çok baytlı karakterler varsa, bu (ve şimdiye kadar yayınlanan diğer tüm çözümler) kesilir.
perl6Çok baytlık karakterlerle bile doğru yapmanın bir yolu olabileceğini düşünüyorum . Ancak öte yandan perl6pek çok yönden sinir bozucu.
PERL_UNICODE='AS'. Örneğin: printf '%s' nóóös | perl -nle 'print length($_)'8 yazdırır ("yanlış") printf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'5 yazdırır ("doğru").
Başka bir yol, yalnızca printfkomutu kullanmak ve önce karakter doldurma desenini oluşturmaktır Shell Brace Expansion( Yazdırmak istediğiniz sayı biçimlendirme alanı ile sonlandırabilirsiniz{1..end} ) ve sadece s %.1solan her ilk karakterini =alıp yalnızca ilk 20 karakter uzunluğunu yazdırabilirsiniz. bunun alanı %.20s. Bu, karakterleri çoğaltmak yerine tekrarlanan karakterlere / kelimelere sahip olmanın daha iyi bir yoludur.
printf '%.20s:\n' "$str$(printf '%.1s' ={1..20})"
Hello World!!=======:
açıklamalar:
Normalde Brace Expansion olarak , {1..20}bunları yazdırırsak kabuk aşağıdaki gibi genişler .
printf '%s ' {1..20}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Yani ona eşit bir işaret ekleyerek ={1..20}, kabuk aşağıdaki gibi genişleyecektir.
printf '%s ' ={1..20}
=1 =2 =3 =4 =5 =6 =7 =8 =9 =10 =11 =12 =13 =14 =15 =16 =17 =18 =19 =20
Ve printf '%.1s'bunun anlamı aslında printf '%WIDE.LENGTH', varsayılan WIDE ile yukarıdakilerden sadece bir UZUNLUĞU yazdırıyoruz . böylece sonuç sadece s ve 20 kez kendini tekrar eder.1 =
Şimdi printf '%.20s:\n'sadece 20 uzunluğunu $strve $str<20 uzunluğunu yazıyoruz, gerisi =boşluk yerine doldurmak için üretilen s'den alacak .