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.