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 :loop
biz bir etiket adında tanımlanır loop
ve birlikte t loop
bir 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 $string
ve ofsetten itibaren ${filler:${#string}}
alt dizisidir.$filler
${#string}
Çıktının toplam genişliği $filler
veya genişliğinin maksimum genişliği olacaktır $string
.
Dolgu dizesi, jot
dinamik 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========================="
%.20s
dize 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.
echo
destekliyorsa -e
. birçok nedenden ötürü printf
neredeyse 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 perl6
pek ç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 printf
komutu 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 %.1s
olan 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 $str
ve $str
<20 uzunluğunu yazıyoruz, gerisi =
boşluk yerine doldurmak için üretilen s'den alacak .