Saya ingin menerapkan fungsi dalam Bash yang meningkatkan (dan mengembalikan) hitungan dengan setiap panggilan. Sayangnya ini tampaknya non-sepele karena saya menjalankan fungsi di dalam subkulit dan akibatnya tidak dapat memodifikasi variabel shell induknya.
Inilah usaha saya:
PS_COUNT=0
ps_count_inc() {
let PS_COUNT=PS_COUNT+1
echo $PS_COUNT
}
ps_count_reset() {
let PS_COUNT=0
}
Ini akan digunakan sebagai berikut (dan karenanya kebutuhan saya untuk memanggil fungsi dari subkulit):
PS1='$(ps_count_reset)> '
PS2='$(ps_count_inc) '
Dengan begitu, saya akan memiliki prompt multi-line bernomor:
> echo 'this
1 is
2 a
3 test'
Imut. Tetapi karena keterbatasan yang disebutkan di atas tidak berhasil.
Solusi yang tidak berfungsi adalah menulis hitungan ke file alih-alih variabel. Namun, ini akan menciptakan konflik antara beberapa sesi, secara bersamaan menjalankan sesi. Saya bisa menambahkan ID proses dari shell ke nama file, tentu saja. Tapi saya berharap ada solusi yang lebih baik yang tidak akan mengacaukan sistem saya dengan banyak file.
man 1 mktemp
.Jawaban:
Untuk mendapatkan hasil yang sama seperti yang Anda catat dalam pertanyaan Anda, yang diperlukan hanyalah ini:
Anda tidak perlu memutarbalikkan. Kedua baris tersebut akan melakukan semuanya dalam shell yang berpura-pura mendekati kompatibilitas POSIX.
Tapi saya suka ini. Dan saya ingin menunjukkan dasar-dasar apa yang membuat pekerjaan ini sedikit lebih baik. Jadi saya sedikit mengedit ini. Saya memasukkannya
/tmp
untuk saat ini tetapi saya pikir saya akan menyimpannya sendiri juga. Itu disini:PROMPT SCRIPT:
Catatan: setelah baru-baru ini belajar tentang yash , saya membangunnya kemarin. Untuk alasan apa pun itu tidak mencetak byte pertama dari setiap argumen dengan
%c
string - meskipun dokumen khusus tentang ekstensi wide-char untuk format itu dan jadi itu mungkin terkait - tetapi tidak apa-apa dengan%.1s
Itu semuanya. Ada dua hal utama yang terjadi di sana. Dan seperti inilah tampilannya:
PARSING
$PWD
TAPI APA TENTANG PENINGKATAN?
Dan terima kasih kepada POSIX yang ditentukan
${parameter} $((expansion))
yang membuat definisi ini di shell saat ini tanpa mengharuskan kita mengaturnya dalam subkulit yang terpisah, terlepas dari di mana kita mengevaluasinya. Dan inilah mengapa ini bekerjadash
dansh
sama baiknya dengan dibash
danzsh
. Kami tidak menggunakan shell / terminal dependent escapes dan kami membiarkan variabel menguji sendiri. Itulah yang membuat kode portabel cepat.Sisanya cukup sederhana - cukup tambahkan penghitung kami untuk setiap kali
$PS2
dievaluasi sampai$PS1
sekali lagi atur ulang. Seperti ini:Jadi sekarang saya bisa:
DASH DEMO
SH DEMO
Ia bekerja sama di
bash
ataush
:Seperti yang saya katakan di atas, masalah utama adalah Anda harus mempertimbangkan di mana Anda melakukan perhitungan. Anda tidak mendapatkan status di shell induk - jadi Anda tidak menghitung di sana. Anda mendapatkan status dalam subkulit - jadi di situlah Anda menghitung. Tapi Anda melakukan definisi di shell induk.
sumber
PS2
? Ini bagian yang sulit. Saya tidak berpikir solusi Anda dapat diterapkan di sini. Jika Anda berpikir sebaliknya, tolong tunjukkan saya caranya.PS1
danPS2
merupakan variabel khusus dalam shell yang dicetak sebagai command prompt (coba dengan menetapkanPS1
ke nilai yang berbeda di jendela shell baru), sehingga mereka digunakan sangat berbeda dari kode Anda. Berikut ini beberapa info lebih lanjut tentang penggunaannya: linuxconfig.org/bash-prompt-basicsecho 'this
pada prompt, lalu jelaskan cara memperbarui nilaiPS2
sebelum mengetikkan kutipan tunggal penutup.Dengan pendekatan ini (fungsi berjalan dalam sebuah subkulit) Anda tidak akan dapat memperbarui status proses master shell tanpa melalui contortions. Alih-alih, atur agar fungsi dijalankan dalam proses master.
Nilai
PROMPT_COMMAND
variabel ditafsirkan sebagai perintah yang dijalankan sebelum mencetakPS1
prompt.Sebab
PS2
, tidak ada yang sebanding. Tetapi Anda dapat menggunakan trik sebagai gantinya: karena semua yang ingin Anda lakukan adalah operasi aritmatika, Anda dapat menggunakan ekspansi aritmatika, yang tidak melibatkan subkulit.Hasil perhitungan aritmatika berakhir di prompt. Jika Anda ingin menyembunyikannya, Anda bisa meneruskannya sebagai subscript array yang tidak ada.
sumber
Agak intensif I / O, tetapi Anda harus menggunakan file sementara untuk menyimpan nilai hitungan.
Jika Anda khawatir tentang perlu file terpisah per sesi shell (yang tampaknya seperti masalah kecil; apakah Anda benar-benar akan mengetik perintah multi-line dalam dua shell yang berbeda pada saat yang sama?), Anda harus menggunakan
mktemp
untuk membuat file baru untuk setiap menggunakan.sumber
Anda tidak dapat menggunakan variabel shell dengan cara ini dan Anda sudah mengerti mengapa. Subkulit mewarisi variabel dengan cara yang sama persis dengan proses mewarisi lingkungannya: setiap perubahan yang dibuat hanya berlaku untuk itu dan anak-anaknya dan tidak untuk proses leluhur.
Seperti jawaban lain, hal termudah untuk dilakukan adalah menyimpan data itu dalam file.
Dll
sumber
mktemp
).PS2
diperluas oleh shell. Anda tidak memiliki kesempatan untuk memperbarui nilai variabel di shell induk pada saat itu.Untuk referensi, inilah solusi saya menggunakan file sementara, yang unik untuk setiap proses shell, dan dihapus sesegera mungkin (untuk menghindari kekacauan, seperti disinggung dalam pertanyaan):
sumber