Me gustaría implementar una función en Bash que aumente (y devuelva) un recuento con cada llamada. Desafortunadamente, esto no parece trivial ya que estoy invocando la función dentro de una subshell y, en consecuencia, no puede modificar las variables de su shell principal.
Aquí está mi intento:
PS_COUNT=0
ps_count_inc() {
let PS_COUNT=PS_COUNT+1
echo $PS_COUNT
}
ps_count_reset() {
let PS_COUNT=0
}
Esto se usaría de la siguiente manera (y, por lo tanto, mi necesidad de invocar las funciones desde una subshell):
PS1='$(ps_count_reset)> '
PS2='$(ps_count_inc) '
De esa manera, tendría un indicador numerado de varias líneas:
> echo 'this
1 is
2 a
3 test'
Linda. Pero debido a la limitación mencionada anteriormente no funciona.
Una solución que no funciona sería escribir el recuento en un archivo en lugar de una variable. Sin embargo, esto crearía un conflicto entre múltiples sesiones que se ejecutan simultáneamente. Por supuesto, podría agregar el ID de proceso del shell al nombre del archivo. Pero espero que haya una mejor solución que no saturará mi sistema con muchos archivos.
man 1 mktemp
.Respuestas:
Para obtener el mismo resultado que anota en su pregunta, todo lo que se necesita es esto:
No necesitas contorsionar. Esas dos líneas lo harán todo en cualquier shell que simule algo cercano a la compatibilidad POSIX.
Pero me ha gustado esto. Y quería demostrar los fundamentos de lo que hace que esto funcione un poco mejor. Así que edité esto un poco. Lo puse
/tmp
por ahora, pero creo que también me lo guardaré. Esta aquí:GUIÓN INMEDIATA:
Nota: habiendo aprendido recientemente de yash , lo construí ayer. Por alguna razón, no imprime el primer byte de cada argumento con la
%c
cadena, aunque los documentos eran específicos sobre las extensiones de ancho ancho para ese formato y, por lo tanto, pueden estar relacionados, pero funciona bien con%.1s
Eso es todo. Hay dos cosas principales que suceden allí arriba. Y así es como se ve:
PARSING
$PWD
¿Pero qué hay del incremento?
Y es gracias a POSIX-especificado
${parameter} $((expansion))
que mantiene estas definiciones en el shell actual sin requerir que las establezcamos en un subshell separado, independientemente de dónde las evaluamos. Y es por eso que funciona endash
ysh
tan bien como enbash
yzsh
. No utilizamos escapes dependientes de shell / terminal y dejamos que las variables se prueben a sí mismas. Eso es lo que hace que el código portátil sea rápido.El resto es bastante simple: solo incremente nuestro contador por cada vez que
$PS2
se evalúe hasta que$PS1
una vez más se restablezca. Me gusta esto:Entonces ahora puedo:
DASH DEMO
SH DEMO
Funciona igual en
bash
osh
:Como dije anteriormente, el problema principal es que debes considerar dónde haces tu cálculo. No obtiene el estado en el shell principal, por lo que no calcula allí. Obtiene el estado en la subshell, así que ahí es donde calcula. Pero haces la definición en el shell principal.
fuente
PS2
? Esta es la parte difícil. No creo que su solución pueda aplicarse aquí. Si piensas lo contrario, muéstrame cómo.PS1
yPS2
son variables especiales en el shell que se imprimen como símbolo del sistema (pruébelo estableciendoPS1
un valor diferente en una nueva ventana del shell), por lo tanto, se usan de manera muy diferente a su código. Aquí hay más información sobre su uso: linuxconfig.org/bash-prompt-basicsecho 'this
en el indicador, luego explique cómo actualizar el valor dePS2
antes de escribir la comilla simple de cierre.Con este enfoque (función que se ejecuta en una subshell), no podrá actualizar el estado del proceso de shell maestro sin sufrir contorsiones. En su lugar, organice la función para que se ejecute en el proceso maestro.
El valor de la
PROMPT_COMMAND
variable se interpreta como un comando que se ejecuta antes de imprimir laPS1
solicitud.por
PS2
no hay nada comparable. Pero puede usar un truco en su lugar: dado que todo lo que quiere hacer es una operación aritmética, puede usar la expansión aritmética, que no implica una subshell.El resultado del cálculo aritmético termina en la solicitud. Si desea ocultarlo, puede pasarlo como un subíndice de matriz que no existe.
fuente
Es un poco intensivo de E / S, pero necesitará usar un archivo temporal para mantener el valor del recuento.
Si le preocupa la necesidad de un archivo separado por sesión de shell (lo que parece una preocupación menor; ¿realmente estará escribiendo comandos de varias líneas en dos shells diferentes al mismo tiempo?), Debe usar
mktemp
para crear un nuevo archivo para cada utilizar.fuente
No puede usar una variable de shell de esta manera y ya comprende por qué. Una subshell hereda variables exactamente de la misma manera que un proceso hereda su entorno: cualquier cambio realizado se aplica solo a él y a sus hijos y no a ningún proceso ancestro.
Según otras respuestas, lo más fácil es guardar esos datos en un archivo.
Etc.
fuente
mktemp
).PS2
el shell expande el valor de . No tiene la oportunidad de actualizar el valor de una variable en el shell principal en ese momento.Como referencia, aquí está mi solución usando archivos temporales, que son únicos por proceso de shell, y eliminados lo antes posible (para evitar el desorden, como se alude en la pregunta):
fuente