ksh93
memiliki disiplin ilmu yang biasanya digunakan untuk hal semacam ini. Dengan zsh
, Anda dapat membajak fitur direktori bernama dinamis :
Tentukan misalnya:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Dan kemudian Anda dapat menggunakan ~[incr]
untuk mendapatkan peningkatan $incr
setiap kali:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Pendekatan Anda gagal karena dalam head -1 /tmp/ints
, kepala membuka fifo, membaca buffer penuh, mencetak satu baris, dan kemudian menutupnya . Setelah ditutup, ujung tulisan melihat pipa rusak.
Sebaliknya, Anda bisa melakukan:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ seq infinity > $fifo &
$ exec 3< $fifo
$ IFS= read -rneu3
1
$ IFS= read -rneu3
2
Di sana, kami membiarkan ujung bacaan terbuka pada fd 3, dan read
membaca satu byte pada satu waktu, bukan buffer penuh untuk memastikan untuk membaca tepat satu baris (hingga karakter baris baru).
Atau Anda bisa melakukannya:
$ fifo=~/.generators/incr
$ (umask 077 && mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo)
$ while true; do echo $((++incr)) > $fifo; done &
$ cat $fifo
1
$ cat $fifo
2
Waktu itu, kami instantiate pipa untuk setiap nilai. Itu memungkinkan pengembalian data yang berisi jumlah garis sembarang.
Namun, dalam kasus itu, segera setelah cat
membuka fifo, echo
loop dan tidak terbuka, sehingga lebih banyak yang echo
dapat dijalankan, pada saat cat
membaca konten dan menutup pipa (menyebabkan berikutnya echo
instantiate pipa baru).
Pekerjaan di sekitar dapat menambahkan beberapa penundaan, seperti misalnya dengan menjalankan eksternal echo
seperti yang disarankan oleh @jimmij atau menambahkan beberapa sleep
, tapi itu masih belum terlalu kuat, atau Anda bisa membuat ulang pipa bernama setelah masing-masing echo
:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Itu masih menyisakan jendela pendek di mana pipa tidak ada (antara unlink()
dilakukan oleh rm
dan mknod()
dilakukan oleh mkfifo
) menyebabkan cat
kegagalan, dan jendela sangat pendek di mana pipa telah dipakai tetapi tidak ada proses akan pernah menulis lagi untuk itu (antara write()
dan close()
dilakukan oleh echo
) menyebabkan cat
tidak menghasilkan apa-apa, dan jendela pendek di mana pipa bernama masih ada tetapi tidak akan pernah membukanya untuk menulis (antara close()
dilakukan oleh echo
dan unlink()
dilakukan oleh rm
) di mana cat
akan menggantung.
Anda dapat menghapus beberapa jendela dengan melakukannya seperti:
fifo=~/.generators/incr
(
umask 077
mkdir -p $fifo:h && rm -f $fifo && mkfifo $fifo &&
while
mkfifo $fifo.new &&
{
mv $fifo.new $fifo &&
echo $((++incr))
} > $fifo
do : nothing
done
) &
Dengan begitu, satu-satunya masalah adalah jika Anda menjalankan beberapa kucing secara bersamaan (mereka semua membuka fifo sebelum loop penulisan kami siap membukanya untuk menulis) dalam hal ini mereka akan membagikan echo
hasilnya.
Saya juga menyarankan untuk tidak membuat nama tetap, fifos yang dapat dibaca dunia (atau file apa pun yang penting) di direktori dunia yang dapat ditulisi seperti /tmp
kecuali jika itu adalah layanan yang akan diekspos kepada semua pengguna pada sistem.
command echo
atau/bin/echo
bukannya bawaanecho
. Juga - Anda dapat membuat perintah ini sedikit memagut pendek:repeat 999 /bin/echo $((++incr)) > /tmp/int &
.Jika Anda ingin mengeksekusi kode setiap kali nilai variabel dibaca, Anda tidak bisa melakukannya di dalam zsh itu sendiri. The
RANDOM
variabel (seperti variabel khusus lainnya yang sejenis) adalah keras-kode dalam kode sumber zsh. Namun Anda dapat mendefinisikan variabel khusus yang serupa dengan menulis modul dalam C. Banyak modul standar menentukan variabel khusus.Anda dapat menggunakan coprocess untuk membuat generator.
Namun ini sangat terbatas karena Anda hanya dapat memiliki satu proses. Cara lain untuk secara progresif mendapatkan output dari suatu proses adalah dengan mengalihkan dari substitusi proses .
Catatan yang
head -1
tidak berfungsi di sini, karena membaca seluruh buffer, mencetak apa yang disukainya, dan keluar. Data yang telah dibaca dari pipa tetap dibaca; ini adalah properti intrinsik dari pipa (Anda tidak dapat memasukkan data kembali). Theread
builtin menghindari masalah ini dengan membaca satu byte pada suatu waktu, yang memungkinkan untuk berhenti secepat itu menemukan baris pertama, tetapi sangat lambat (tentu saja itu tidak masalah jika Anda hanya membaca beberapa ratus byte).sumber
bash
, lihat bagian bash di tautan itu.coproc
Proses ulang, maksud saya, bukan yang zpty)coproc cmd1; exec 3>&p 4<&p; coproc cmd2 3>&- 4<&-...
Saya pikir saya akan melakukannya dengan semacam sinyal.
Itu bekerja untuk saya.
Pada catatan yang hanya sedikit berhubungan, ada sesuatu yang aneh yang saya temukan di hari lain:
Semakin aneh juga:
sumber
bash
tingkah lakunya telah berubah? Saya pikir pernyataan tentangpwd
tidak memeriksa dan merujuk hanya$PWD
salah.mkdir /tmp/dir; cd $_; PS4='$OLDPWD, $PWD + '; set -x; OLDPWD=$OLDPWD PWD=$PWD command eval ' cd ..; cd ..; cd ~; pwd'; pwd; cd .; pwd
mungkin menunjukkan apa yang saya maksud. Ini masalah yang mengganggu saya denganns()
hal ini .