ksh93tiene disciplinas que generalmente se usan para este tipo de cosas. Con zsh, podría secuestrar la función de directorio dinámico con nombre :
Definir por ejemplo:
zsh_directory_name() {
case $1 in
(n)
case $2 in
(incr) reply=($((++incr)))
esac
esac
}
Y luego puede usar ~[incr]para obtener un incremento $incrcada vez:
$ echo ~[incr]
1
$ echo ~[incr] ~[incr]
2 3
Su enfoque falla porque en head -1 /tmp/ints, head abre el fifo, lee un búfer completo, imprime una línea y luego la cierra . Una vez cerrado, el final de la escritura ve una tubería rota.
En cambio, podrías hacer lo siguiente:
$ 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
Allí, dejamos abierto el final de lectura en fd 3 y readlee un byte a la vez, no un búfer completo para asegurarnos de leer exactamente una línea (hasta el carácter de nueva línea).
O podrías hacer:
$ 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
Esa vez, instanciamos una tubería para cada valor. Eso permite devolver datos que contienen cualquier número arbitrario de líneas.
Sin embargo, en ese caso, tan pronto como se catabre el fifo, echose desbloquea el bucle y, por lo que echopodría ejecutarse más, para cuando catlea el contenido y cierre la tubería (haciendo que la próxima echoinstancia una nueva tubería).
Una echosolución podría ser agregar algún retraso, como por ejemplo ejecutando un externo como lo sugiere @jimmij o agregar algunos sleep, pero eso aún no sería muy robusto, o podría recrear la tubería con nombre después de cada uno echo:
while
mkfifo $fifo &&
echo $((++incr)) > $fifo &&
rm -f $fifo
do : nothing
done &
Eso todavía deja ventanas cortas donde la tubería no existe (entre el unlink()hecho por rmy el mknod()hecho por mkfifo) haciendo catque falle, y ventanas muy cortas donde la tubería ha sido instanciada pero ningún proceso volverá a escribirle (entre el write()y el close()hecho por echo) haciendo catque no se devuelva nada, y las ventanas cortas donde todavía existe la tubería nombrada pero nada la abrirá para escribir (entre close()hecho por echoy unlink()hecho por rm) donde catse bloqueará.
Puede eliminar algunas de esas ventanas haciéndolo como:
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
) &
De esa manera, el único problema es si ejecuta varios cat al mismo tiempo (todos abren el fifo antes de que nuestro bucle de escritura esté listo para abrirlo para escribir) en cuyo caso compartirán la echosalida.
También recomendaría no crear nombres fijos, juegos legibles en todo el mundo (o cualquier archivo que importe) en directorios de escritura mundial, a /tmpmenos que sea un servicio que se exponga a todos los usuarios del sistema.
command echoo en/bin/echolugar de integradoecho. También - usted puede hacer este comando un poco más corto:repeat 999 /bin/echo $((++incr)) > /tmp/int &.Si desea ejecutar código cada vez que se lee el valor de una variable, no puede hacerlo dentro de zsh. La
RANDOMvariable (como otras variables especiales similares) está codificada en el código fuente zsh. Sin embargo, puede definir variables especiales similares escribiendo un módulo en C. Muchos de los módulos estándar definen variables especiales.Puedes usar un coproceso para hacer un generador.
Sin embargo, esto es bastante limitado porque solo puede tener un coproceso. Otra forma de obtener progresivamente la salida de un proceso es redirigir desde una sustitución de proceso .
Tenga en cuenta que
head -1no funciona aquí, porque lee un búfer completo, imprime lo que le gusta y sale. Los datos que se han leído de la tubería siguen siendo leídos; Esta es una propiedad intrínseca de las tuberías (no se pueden volver a introducir datos). Elreadbuiltin evita este problema al leer un byte a la vez, lo que le permite detenerse tan pronto como encuentra la primera línea nueva pero es muy lento (por supuesto, eso no importa si solo está leyendo unos pocos cientos de bytes).fuente
bash, consulte la sección bash en ese enlace.coproccoprocesos, quiero decir, no zpty)coproc cmd1; exec 3>&p 4<&p; coproc cmd2 3>&- 4<&-...Creo que lo haría con una señal de algún tipo.
Funciona para mí de todos modos.
En una nota ligeramente relacionada, aquí hay algo extraño que descubrí el otro día:
También se vuelve más extraño:
fuente
bashel comportamiento ha cambiado? Creo que la afirmación sobrepwdno verificar y referirse solo$PWDes incorrecta.mkdir /tmp/dir; cd $_; PS4='$OLDPWD, $PWD + '; set -x; OLDPWD=$OLDPWD PWD=$PWD command eval ' cd ..; cd ..; cd ~; pwd'; pwd; cd .; pwdpodría mostrarte lo que quiero decir. Es un problema que me molestó con estons().