Jawaban yang diperbarui menjadi solusi yang lebih umum. lihat juga jawaban saya yang lain di bawah ini hanya menggunakan ekspansi brace shell dan pritnf
.
$ str='Hello World!'
$ sed -r ':loop; s/ (=*):$/\1=:/; t loop' <<< "$(printf '%-20s:\n' "$str" )"
Hello World!========:
Bagaimana itu bekerja?
ini (=*):$/
menangkap satu ruang, satu atau lebih =
yang diikuti oleh titik dua :
di akhir inputnya; kami menjadikan set =
sebagai pertandingan grup dan \1
akan menjadi referensi kembali.
Dengan :loop
kami mendefinisikan label bernama loop
dan dengan t loop
itu akan melompat ke label itu ketika s/ (=*):$/\1=:/
telah melakukan penggantian yang sukses;
Di bagian pengganti dengan \1=:
, itu akan selalu menambah jumlah =
s dan kembali usus besar itu sendiri ke akhir string.
Memberi
${#string}
adalah panjang dari nilai$string
, dan${filler:${#string}}
merupakan substring dari$filler
dari offset${#string}
dan seterusnya.Lebar total output akan menjadi lebar maksimum
$filler
atau$string
.String pengisi dapat, pada sistem yang telah
jot
, dibuat secara dinamis menggunakan(untuk 16
=
baris). Sistem GNU dapat menggunakanseq
:Sistem lain mungkin menggunakan Perl atau cara lain yang lebih cepat untuk membuat string secara dinamis.
sumber
printf
untuk menghasilkan filter yang hampir tersedia di semua sistem dan ekspansi penjepit dengan shell sepertibash/szh
?printf
+ ekspansi bracebash
?di mana
%.20s
format pemotongan stringsumber
Salah satu cara untuk melakukannya:
sumber
====================\rhello world
, yang mungkin menjadi masalah jika OP perlu menyimpan ini dan tidak hanya mencetaknya ke layar.echo -e '=================\rHello World!!'
, tetapi memiliki masalah yang sama dengan @terdon menunjuk itu.echo
mendukung-e
.printf
hampir selalu lebih baik daripadaecho
, karena berbagai alasan.Pendekatan Perl:
Atau, lebih baik, @SatoKatsura tunjukkan dalam komentar:
Jika Anda perlu mendukung karakter multi-byte UTF, gunakan:
Gagasan yang sama di shell:
sumber
perl -le '$k = "hello world!!"; print $k, "=" x (20-length $k), "\n"'
. Namun, ini (dan semua solusi lain yang diposting sejauh ini) rusak jika karakter multi-byte terlibat.perl6
mungkin memiliki cara untuk melakukannya dengan benar bahkan dengan karakter multi-byte. Tetapi di sisi lainperl6
menjengkelkan dalam banyak hal.PERL_UNICODE='AS'
. Misalnya:printf '%s' nóóös | perl -nle 'print length($_)'
mencetak 8 ("salah") saatprintf '%s' nóóös | PERL_UNICODE='AS' perl -nle 'print length($_)'
mencetak 5 ("benar").Cara lain adalah dengan hanya menggunakan
printf
perintah dan menghasilkan pola karakter padding pertama denganShell Brace Expansion
(Anda dapat mengakhiri dengan angka ≥ area format yang ingin Anda cetak{1..end}
) dan dapatkan hanya setiap karakter pertama%.1s
yang=
s dan kemudian hanya mencetak panjang 20 karakter pertama daerah itu%.20s
. Ini semacam cara yang lebih baik untuk mengulangi karakter / kata daripada menduplikasinya.Penjelasan:
Biasanya sebagai Brace Expansion , shell mengembang
{1..20}
sebagai berikut jika kita mencetaknya.Jadi dengan menambahkan tanda sama dengan itu
={1..20}
, shell akan berkembang sebagai berikut.Dan dengan
printf '%.1s'
yang sebenarnya berartiprintf '%WIDE.LENGTH'
, kami mencetak hanya satu PANJANG dari yang di atas dengan1
WIDE default . jadi akan menghasilkan=
s hanya dan 20 kali diulang sendiri.Sekarang dengan
printf '%.20s:\n'
kita mencetak hanya 20 panjang$str
dan jika panjang$str
<20, sisanya akan mengambil dari yang dihasilkan=
untuk mengisi bukan spasi.sumber