Penjelasan diperlukan tentang bagaimana saya dapat mengulangi karakter dalam shell POSIX

8

Jawaban berikut tentang Stack Overflow,

Bagaimana saya bisa mengulang karakter dalam bash?

memaksakan satu cara POSIX yang masuk akal - mengulangi satu karakter, sebagai berikut. Dalam contoh ini, mari kita gunakan tanda sama dengan 100 kali:

printf %100s | tr " " "="

Masalah saya adalah saya tidak mengerti cara kerjanya, dan saya lebih suka penjelasan langsung. Tolong jangan komentar seperti membaca manual , saya melakukannya, dan karena saya tidak pandai dari itu, saya mengajukan pertanyaan ini karena saya tidak pernah menggunakan tr, atau melihat printfpernyataan seperti itu .

LinuxSecurityFreak
sumber

Jawaban:

13

Singkatnya, printf %100sakan mencetak 100 spasi, dan tr " " "="akan mengkonversi ruang-ruang itu menjadi tanda sama dengan, secara efektif mencetak 100 tanda sama.

Hancurkan:


printfadalah shell built-in. Biasanya diperlukan dua argumen atau lebih, yang pertama adalah "format string" dan sisanya akan digunakan untuk mengisi placeholder dalam string format itu. Setelah template itu terisi penuh, itu akan mencetak hasilnya. Jika ada lebih banyak argumen yang tersisa, itu akan memulai kembali, mengisi lebih banyak argumen dan mencetak string yang dihasilkan.

String format yang digunakan untuk printfmengambil spesifikasi format, yang dimulai dengan %dan diakhiri dengan satu huruf, jadi %dberarti integer (menggunakan basis desimal, oleh karena itu "d"), %fberarti angka titik-mengambang dan %sberarti serangkaian karakter. Karakter selain huruf setelah %pengubah untuk spesifikasi format dan, khususnya, angka digunakan untuk menentukan panjang bidang yang diminta pada output. Jadi %100sakan memformat string untuk memiliki setidaknya 100 karakter, itu akan pad dengan spasi dan itu akan tetap selaras (dengan kata lain, tambahkan spasi di awal string.)

Jika melewati argumen tambahan, itu akan menggunakannya untuk %sbidang itu, jadi misalnya printf %100s abcakan mencetak 97 spasi (untuk mendapatkan total 100, mengingat 3 pada "abc") diikuti oleh string "abc" yang sebenarnya. Tetapi jika tidak ada argumen yang diberikan, maka spesifikasi format diisi dengan argumen kosong atau nol (yang merupakan string kosong untuk %s, itu akan menjadi 0 untuk %d, dll.) Jadi itu sama seperti jika string kosong dilewatkan, seperti printf %100s ''. Hasil akhirnya adalah hanya lapisan 100 karakter yang dicetak.

Jadi, menyatukan semuanya, printf %100smenghasilkan 100 ruang yang dicetak.


Sekarang tradalah alat untuk menerjemahkan karakter dari input ke output. Dibutuhkan dua argumen, SET1 dan SET2, masing-masing satu set karakter, dan kemudian menerjemahkan karakter pertama SET1 menjadi yang pertama dari SET2, karakter kedua SET1 ke dalam kedua SET2 dan seterusnya. trmembaca inputnya dari stdin dan menulisnya kembali ke stdout (jadi itu sangat berguna dalam pipa seperti yang di atas.) trakan selalu menerjemahkan semua kemunculan karakter itu dalam string yang diberikan.

Misalnya, tr aeiou 12345akan menerjemahkan huruf kecil ke angka 1 hingga 5 dalam urutan itu, jadi itu akan menerjemahkan "antrian" menjadi "q52523ng" misalnya. Anda juga dapat meneruskannya rentang karakter, seperti tr a-z A-Zmengubah huruf kecil apa pun menjadi huruf besar yang sesuai.

Jadi tr " " "="hanya menerjemahkan spasi menjadi tanda yang sama di seluruh string. Ruang pertama harus dikutip agar diakui sebagai argumen. The =tidak benar-benar perlu untuk dikutip, tetapi melakukan hal itu tidak sakit. tr " " =akan bekerja sama.


Menyatukan semuanya, cetak 100 spasi, lalu terjemahkan masing-masing ke dalam tanda yang sama.

Semoga ini menjelaskan dengan cukup detail, tetapi jika masih ada sesuatu yang Anda tidak mengerti, silakan tinggalkan komentar dan saya akan mencoba mengatasinya.

filbranden
sumber
Hanya memeriksa, apakah yang berikut ini secara sintaksis benar ?:printf '%100s' ' ' | tr " " "="
LinuxSecurityFreak
2
@Vastimil Sebenarnya printf '%100s' '', dengan string kosong ... Saya memperbarui jawaban untuk memasukkan itu. Dalam kasus khusus ini, string kosong atau spasi tunggal tidak akan membuat perbedaan, tetapi Anda dapat melihat perbedaannya printf '%sx\n', yang sama printf '%sx\n' ''tetapi berbeda dari printf '%sx\n' ' '. Saya harap itu membantu!
filbranden
1
+1 untuk menyebutkan yang trberoperasi pada set karakter. Ini sering ditinggalkan.
Sergiy Kolodyazhnyy
11

The printfperintah menggunakan argumen pertama sebagai format untuk mencetak argumen selanjutnya. printf %100smencetak argumennya dengan lebar 100 karakter, menggunakan spasi (di sebelah kiri). Tidak ada argumen yang diberikan untuk memformat, sehingga memformat string kosong satu kali, dan menghasilkan 100 spasi. Anda dapat melihat bahwa:

$ printf %100s | hexdump -C
00000000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
*
00000064

(20 adalah hex untuk spasi; *berarti baris sebelumnya diulang)

String format menggunakan kira-kira Xprintfspecifier C %:, lebar opsional agar sesuai dengan nilai yang diformat, dan tipe format yang digunakan. sadalah pemformatan string, dan string diisi dengan spasi di sebelah kiri secara default. Mungkin ada beberapa format, atau bagian literal lainnya: printf "a%10sb\n" hellocetak

 a         xb.

trmengganti karakter yang dipilih dalam input standar dengan penggantian yang dipilih , dan mencetak hasilnya ke output standarnya. tr " " "="memiliki karakter tunggal untuk diganti - spasi - dan karakter tunggal untuk menggantinya dengan - tanda sama dengan. Dengan demikian mengubah setiap ruang di input menjadi =, dan meninggalkan sisanya tidak berubah. Anda dapat mencobanya juga:

$ tr " " "="
hello world
hello=world

(Saya mengetik "hello world")

Anda bisa memiliki beberapa penggantian: tr abc defmengubah a menjadi d, b menjadi e, c menjadi f, dan membiarkan sisanya tidak berubah. Ini hanya satu karakter, karena itulah yang printfbisa murah.

Pipa |menyebabkan output dari perintah di sebelah kiri printf %100s,, untuk digunakan sebagai input ke perintah di sebelah kanan tr " " "=",. Yaitu, seratus ruang berturut-turut diberikan tr, dan masing-masing diganti dengan =, dengan string baru dicetak.

printf %100s | tr " " "="
====================================================================================================
Michael Homer
sumber
Hanya memeriksa, apakah yang berikut ini secara sintaksis benar ?:printf '%100s' ' ' | tr " " "="
LinuxSecurityFreak
1
Memformat spasi dan menambahkannya dengan spasi akan memberikan hasil yang sama dengan memformat string kosong dan melapisi dengan spasi, tetapi tidak secara struktural setara. Mungkin lebih "benar" dalam hal kejelasan tentang apa yang terjadi, tetapi tidak secara sintaksis, dan mereka adalah perintah yang berbeda.
Michael Homer