Tengo un script en un archivo llamado instancia:
echo "hello world"
echo ${1}
Y cuando ejecuto este script usando:
./instance solfish
Me sale esta salida:
hello world
solfish
Pero cuando corro:
echo $#
Dice "0". ¿Por qué? No entiendo lo que $#
significa.
Por favor explícalo.
$#
? ¿Qué quieres lograr? ¿De dónde sacaste este comando? No es relevante en absoluto.echo $#
y volvió, lo0
cual es normal. Te sorprendió esto, pero no explicas qué estabas esperando o por qué te sorprendiste. Por lo tanto, nos ayudaría a darle una mejor respuesta si explicara lo que esperaba. Lo que pensaste queecho $#
haría. Si corrieras./instance solfish
y./instance
contuvierasecho $#
, se imprimiría1
y no0
.Respuestas:
$#
es una variable especial enbash
, que se expande a la cantidad de argumentos (parámetros posicionales), es decir,$1, $2 ...
pasados al script en cuestión o al shell en caso de que el argumento pase directamente al shell, por ejemplo, inbash -c '...' ....
.Esto es similar a
argc
en C.Quizás esto lo aclare:
Tenga en cuenta que,
bash -c
toma el argumento después del comando que lo sigue a partir de 0 ($0
; técnicamente, es solobash
la forma de dejarlo establecer$0
, no un argumento realmente), por lo que_
se usa aquí solo como marcador de posición; Los argumentos reales sonx
($1
),y
($2
) yz
($3
).Del mismo modo, en su secuencia de comandos (suponiendo
script.sh
) si tiene:Entonces cuando lo haces:
el script generará 2; igualmente,
dará salida a 1.
fuente
bash -c
, el comportamiento es diferente que si ejecuta un script de shell ejecutable, porque en el último caso el argumento con el índice 0 es el comando de shell utilizado para invocarlo. Como tal, creo que la forma de arreglar esta respuesta es cambiarla para ejecutar scripts como archivos en lugar de usarlosbash -c
, ya que así lo hacía el autor de la pregunta.$0
sería el guión mismo; argumentos serían$1, $2, $3...
.bash -c
el comportamiento es diferente, ya que está destinado a un uso no interactivo y los argumentos que siguen al comando comenzarían$0
, lo he mencionado claramente, creo.bash -c
, debe pasarbash
un nombre significativo como relleno para el 0º argumento.bash -c 'echo "$@"' foo bar
solo imprimebar
, porque"$@"
no incluye$0
, igual que siempre.bash -c
no "convierte a $ 0 en uno de los argumentos", simplemente le permite establecer "$ 0" de la misma manera que cuando ejecuta un programa con laexecve
llamada al sistema o cualquier forma de shell de anular el 0º argumento.$0
nunca debe considerarse "uno de los argumentos".echo $#
genera el número de parámetros posicionales de su script.No tiene ninguno, por lo que genera 0.
echo $#
es útil dentro del script, no como un comando separado.Si ejecuta un script con algunos parámetros como
el
echo $#
colocado en el script generará 2.fuente
echo $#
a su script y luego se ejecuta nuevamente./instance solfish
, debería obtener una línea de salida adicional1
ya que proporcionó 1 parámetro$#
normalmente se usa en scripts bash para garantizar que se pasa un parámetro. En general, verifica si hay un parámetro al comienzo de su script.Por ejemplo, aquí hay un fragmento de un script en el que estaba trabajando hoy:
Para resumir
$#
informes, el número de parámetros pasados a un script. En su caso, no pasó ningún parámetro y el resultado informado es0
.Otros
#
usos en BashA
#
menudo se usa en bash para contar el número de ocurrencias o la longitud de una variable.Para encontrar la longitud de una cadena:
devoluciones:
11
Para encontrar el número de elementos de la matriz:
devoluciones:
3
Para encontrar la longitud del primer elemento de matriz:
devuelve:
1
(La longitud deA
, 0 es el primer elemento ya que las matrices usan índices / subíndices basados en cero).fuente
$# -ne 1
? ¿Por qué no$# -le 0
o equivalente?$#
es el número de argumentos, pero recuerde que será diferente en una función.$#
es el número de parámetros posicionales pasados al script, shell o función de shell . Esto se debe a que, mientras se ejecuta una función de shell, los parámetros posicionales se reemplazan temporalmente con los argumentos de la función . Esto permite que las funciones acepten y usen sus propios parámetros posicionales.Este script siempre se imprime
3
, independientemente de cuántos argumentos se pasaron al script en sí, porque"$#"
en la función sef
expande a la cantidad de argumentos pasados a la función:Esto es importante porque significa que un código como este no funciona como cabría esperar, si no está familiarizado con el funcionamiento de los parámetros posicionales en las funciones de shell:
En
check_args
, se$#
expande al número de argumentos pasados a la función en sí, que en ese script siempre es 0.Si desea dicha funcionalidad en una función de shell, tendría que escribir algo como esto en su lugar:
Esto funciona porque
$#
se expande fuera de la función y se pasa a la función como uno de sus parámetros posicionales. Dentro de la función, se$1
expande al primer parámetro posicional que se pasó a la función de shell, en lugar de al script del que forma parte.Por lo tanto, al igual que
$#
, los parámetros especiales$1
,$2
, etc., así como$@
y$*
, también pertenecen a los argumentos pasados a una función, cuando se expanden en la función. Sin embargo,$0
no no cambiar el nombre de la función, que es por lo que todavía era capaz de utilizarlo para producir un mensaje de error de la calidad.Del mismo modo, si define una función dentro de otra, está trabajando con los parámetros posicionales pasados a la función más interna en la que se realiza la expansión:
Llamé a este script
nested
y (después de ejecutarlochmod +x nested
) lo ejecuté:Sí, lo sé. "1 argumentos" es un error de pluralización.
Los parámetros posicionales también se pueden cambiar.
Si está escribiendo un script, los parámetros posicionales fuera de una función serán los argumentos de la línea de comandos pasados al script a menos que los haya cambiado .
Una forma común de cambiarlos es con el
shift
incorporado, que desplaza cada parámetro posicional hacia la izquierda en uno, bajando el primero y disminuyendo$#
en 1:También se pueden cambiar con el
set
incorporado:fuente