Bir dizede izleyen boşlukları başka bir karakterle doldurma


12

hello world20 karakterden fazla çıktı almak istiyorum .

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

# Actual output
hello world!!        :

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

Ancak, boşluklarla değil, bunun yerine " = " ile tamamlamak istiyorum . Bunu nasıl yaparım?

Yanıtlar:


9

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.


1
yani girişin kaç kelimesine bağlı olarak bayrağı ayarlamanız gerekir?
user1686

@grawity Şimdi genel çözüme cevabımı güncelledim.
αғsнιη

20
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.


@sddgob Bunu printf+ ayraç genişletmesi ile nasıl yaparsınız bash?
Kusalananda

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

%.20sdize kesme biçimi nerede


2
Bu IMHO, benimkinden daha iyi bir çözüm. Biçim dizesinin kısa bir açıklaması gerekir.
Kusalananda

12

Bunu yapmanın bir yolu:

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

6
Ha! Bu akıllıca bir numara! Bununla birlikte, aslında yazdırılacaktır ====================\rhello world, bu da OP'nin bunu sadece ekrana yazdırmakla kalmaması için saklaması gerekiyorsa bir sorun olabilir.
terdon

Ayrıca echo -e '=================\rHello World!!', @terdon ile aynı konuya işaret etti.
αғsнιη

1
@ αғsнιη Yalnızca echodestekliyorsa -e. birçok nedenden ötürü printfneredeyse her zaman daha iyidir echo.
Satō Katsura

5

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"

Bir döngü gerekmez: 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.
Satō Katsura

@ SatōKatsura ooh, evet, bu temiz! Bunu düşünmeliydim, teşekkürler. Ve evet, UTF çok baytlı karakterlerde olası başarısızlık için bir feragatname eklemeyi düşünüyordum, ancak bu bağlamda gereksiz bir komplikasyon olacağını düşündüm.
terdon

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.
Satō Katsura

@ SatōKatsura iyi, bu tür basit bir şey için, sadece ayarlamak yeterli olmalı 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").
terdon

5

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 .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.