Masalah dalam memahami cara kerja set

0

Dapatkah seseorang tolong bantu saya memahami segmen kode berikut?

set -- ${BACKUPDIR}/backup-???.tgz
lastname=${!#}
backupnr=${lastname##*backup-}
backupnr=${backupnr%%.*}
backupnr=${backupnr//\?/0}
backupnr=$[10#${backupnr}]

Saya menemukannya di skrip cadangan ini https://wiki.ubuntuusers.de/Skripte/inkrementelles_Backup/ di mana ia digunakan untuk mendapatkan nomor nama file dari cadangan yang disimpan terakhir. Nama file cadangan adalah "backup-ccc.tgz" di mana ccc adalah angka tiga digit yang bertambah setiap kali cadangan baru dibuat.

Saya mengerti baris tiga dan empat mereka memotong sisa nama file sehingga hanya bagian yang diperlukan dengan nomor yang tersisa. Yang tidak saya dapatkan adalah bagaimana dua baris pertama bekerja. Saya membaca halaman manual set tetapi sekarang saya lebih bingung daripada sebelumnya. Apa yang dilakukan perintah set -- filename? Juga untuk apa tepatnya opsi $ {! #}, Yang disimpan dalam nama belakang. Saya pikir $ {} adalah untuk menentukan parameter yang diberikan, tetapi parameter mana yang dipilih! # Tunjuk ke?

Kedua saya tidak mengerti mengapa saya membutuhkan perintah di baris 5. Seperti yang saya pahami, ini digunakan untuk mengganti semua tanda tanya dengan 0 yang disimpan dalam variabel backupnr, tetapi mengapa ini dilakukan? Jika belum ada kesalahan dalam perintah sebelum backupnr harus berupa angka tiga digit, jika ada kesalahan dan konten variabel rusak, Anda tidak bisa tahu apa nilai aktual backupnr. Jadi jika saya ingin memindai korupsi, mengapa saya tidak memindai semua yang bukan angka, tetapi hanya untuk tanda tanya? Apakah ini mungkin terkait dengan apa yang terjadi di dua baris pertama?

Asco
sumber

Jawaban:

1

setsering digunakan untuk mengatur parameter posisi ( $1, $2, $3, dll, yang biasanya disediakan sebagai argumen untuk script). Dengan menggunakan parameter ini, kita bisa mendapatkan cara sederhana untuk menghitung hal-hal melalui $#variabel, yang menyimpan jumlah parameter posisi yang ditetapkan.

?adalah wildcard yang cocok dengan karakter tunggal mana pun, jadi ???cocok dengan kombinasi tiga karakter apa pun.

Gabungan: set -- ${BACKUPDIR}/backup-???.tgzmengatur setiap file bernama backup-xxx.tgz, di mana xxxada tiga karakter, sebagai parameter.

${!#}, menggunakan tipuan variabel :

Jika karakter pertama dari parameter adalah tanda seru (!), Itu akan memberikan tingkat tipuan variabel. Bash menggunakan nilai variabel yang dibentuk dari sisa parameter sebagai nama variabel; variabel ini kemudian diperluas dan nilai itu digunakan di seluruh substitusi, bukan nilai parameter itu sendiri. Ini dikenal sebagai ekspansi tidak langsung.

Karena $#, itulah yang Anda dapatkan ketika Anda menghapus !, adalah hitungan parameter (dan jumlah parameter terakhir), ${!#}adalah cara sederhana untuk mendapatkan argumen terakhir.


Sedangkan untuk perintah 5, apa yang terjadi ketika tidak ada file yang cocok?

$ bash -c 'set -- backup-???.tgz; echo "$@"'
backup-???.tgz

Shell meninggalkan kata itu sendirian, jadi sekarang kita hanya memiliki literal backup-???.tgz. Penulis menangani kasing tepi dengan mengganti ?dengan 0, untuk menandai file cadangan pertama.

muru
sumber
Jadi jika saya menggunakan set, saya akan membuat parameter posisi baru, yang akan selalu memiliki indeks dari parameter yang sudah ada terakhir yang bertambah satu? Tetapi mengapa penulis menggunakan set -- ${BACKUPDIR}/backup-???.tgzdan bukan hanya set ${BACKUPDIR}/backup-???.tgztanpa -?
Asco
@ Asco tidak ada yang tahu apa yang BACKUPDIRmungkin mengandung. setjuga dapat digunakan untuk mengatur pilihan shell ( set -e, set -f, dll). Agar aman, ia --mengatakan setuntuk berhenti memperlakukan argumen yang tersisa sebagai opsi ot set.
muru