57 votes

Que signifie $# dans bash ?

J'ai un script dans un fichier nommé instance :

echo "hello world"
echo ${1}

Et quand je lance ce script en utilisant :

./instance solfish

J'obtiens ce résultat :

hello world
solfish

Mais quand je cours :

echo $# 

C'est écrit "0". Pourquoi ? Je ne comprends pas ce que $# signifie.

Veuillez l'expliquer.

101voto

heemayl Points 85741

$# est une variable spéciale dans bash qui s'étend au nombre d'arguments (paramètres positionnels), soit $1, $2 ... passé au script en question ou au script en cas d'argument directement passé au script par exemple dans bash -c '...' .... .

Ceci est similaire à argc en C.


Peut-être que cela rendra les choses plus claires :

$ bash -c 'echo $#'
0

$ bash -c 'echo $#' _ x
1

$ bash -c 'echo $#' _ x y
2

$ bash -c 'echo $#' _ x y z
3

Notez que, bash -c prend l'argument après la commande qui le suit en commençant par 0 ( $0 ; techniquement, c'est juste bash C'est la façon qu'a le gouvernement de vous laisser mettre $0 (ce qui n'est pas vraiment un argument), donc _ est utilisé ici juste comme un substitut ; les arguments réels sont x ( $1 ), y ( $2 ), et z ( $3 ).


De la même manière, dans votre script (en supposant que script.sh ) si vous avez :

#!/usr/bin/env bash
echo "$#"

Alors quand tu le feras :

./script.sh foo bar

le script produira 2 ; de même,

./script.sh foo

donnera la valeur 1.

18voto

user167850 Points 230

echo $# sort le nombre de paramètres positionnels de votre script.

Vous n'en avez pas, donc il sort 0.

echo $# est utile à l'intérieur du script, pas comme une commande séparée.

Si vous exécutez un script avec des paramètres comme

./instance par1 par2

le site echo $# placé dans le script produira 2.

16voto

WinEunuuchs2Unix Points 91128

$# est typiquement utilisé dans les scripts de bash pour s'assurer qu'un paramètre est passé. Généralement, vous vérifiez la présence d'un paramètre au début de votre scripts.

Par exemple, voici un extrait d'un script sur lequel je travaillais aujourd'hui :

if [[ $# -ne 1 ]]; then
    echo 'One argument required for the file name, e.g. "Backup-2017-07-25"'
    echo '.tar will automatically be added as a file extension'
    exit 1
fi

Pour résumer $# rapporte le nombre de paramètres passés à un script. Dans votre cas, vous n'avez passé aucun paramètre et le résultat rapporté est 0 .


Autre # utilisations dans Bash

Le site # est souvent utilisé dans bash pour compter le nombre d'occurrences ou la longueur d'une variable.

Pour trouver la longueur d'une corde :

myvar="some string"; echo ${#myvar}

retours : 11

Pour trouver le nombre d'éléments d'un tableau :

myArr=(A B C); echo ${#myArr[@]}

retours : 3

Pour trouver la longueur du premier élément du tableau :

myArr=(A B C); echo ${#myArr[0]}

retours : 1 (La longueur de A 0 est le premier élément, car les tableaux utilisent des indices/souscripts basés sur zéro).

11voto

Eliah Kagan Points 111731

$# est le nombre d'arguments, mais n'oubliez pas qu'il sera différent dans une fonction.

$# est le nombre de paramètres positionnels passés au script, script, ou la fonction Shell. . En effet, pendant qu'une fonction Shell est en cours d'exécution, la fonction les paramètres positionnels sont temporairement remplacés par les arguments de la fonction . Cela permet aux fonctions d'accepter et d'utiliser leurs propres paramètres positionnels.

Ce script imprime toujours 3 quel que soit le nombre d'arguments passés au script lui-même, parce que "$#" dans la fonction f s'étend au nombre d'arguments passés à la fonction :

#!/bin/sh

f() {
    echo "$#"
}

f a b c

C'est important car cela signifie que le code comme celui-ci ne fonctionne pas comme vous pourriez vous y attendre, si vous n'êtes pas familier avec la façon dont les paramètres positionnels fonctionnent dans les fonctions Shell :

#!/bin/sh

check_args() { # doesn't work!
    if [ "$#" -ne 2 ]; then
        printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
        exit 1
    fi
}

# Maybe check some other things...
check_args
# Do other stuff...

Sur check_args , $# s'étend au nombre d'arguments passés à la fonction elle-même, qui dans ce script est toujours 0.

Si vous voulez une telle fonctionnalité dans une fonction Shell, vous devrez écrire quelque chose comme ceci à la place :

#!/bin/sh

check_args() { # works -- the caller must pass the number of arguments received
    if [ "$1" -ne 2 ]; then
        printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
        exit 1
    fi
}

# Maybe check some other things...
check_args "$#"

Cela fonctionne parce que $# est élargi à l'extérieur de la fonction et transmis à la fonction comme l'un des éléments suivants son paramètres de position. A l'intérieur de la fonction, $1 s'étend au premier paramètre positionnel qui a été passé à la fonction Shell, plutôt qu'au Shell dont elle fait partie.

Ainsi, comme $# les paramètres spéciaux $1 , $2 etc., ainsi que $@ y $* se rapportent également aux arguments passés à une fonction, lorsqu'ils sont développés dans la fonction. Cependant, $0 fait ノット au nom de la fonction, ce qui explique que j'ai pu l'utiliser pour produire un message d'erreur de qualité.

$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3

De même, si vous définissez une fonction à l'intérieur d'une autre, vous travaillez avec les paramètres positionnels transmis à la fonction la plus interne dans laquelle l'expansion est effectuée :

#!/bin/sh

outer() {
    inner() {
        printf 'inner() got %d arguments\n' "$#"
    }

    printf 'outer() got %d arguments\n' "$#"
    inner x y z
}

printf 'script got %d arguments\n' "$#"
outer p q

J'ai appelé ce script nested et (après avoir exécuté chmod +x nested ) Je l'ai fait :

$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments

Oui, je sais. "1 arguments" est un bug de pluralisation.

Les paramètres de position peuvent également être modifiés.

Si vous écrivez un script, les paramètres positionnels en dehors d'une fonction seront les arguments de la ligne de commande passés au script. à moins que vous ne les ayez changés .

Une façon courante de les modifier est d'utiliser la fonction shift qui décale chaque paramètre positionnel vers la gauche d'une unité, en supprimant le premier et en diminuant le second. $# par 1 :

#!/bin/sh

while [ "$#"  -ne 0 ]; do
    printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
    shift
done

$ ./do-shift foo bar baz      # I named the script do-shift.
3 argument(s) remaining.
Got "foo".

2 argument(s) remaining.
Got "bar".

1 argument(s) remaining.
Got "baz".

Ils peuvent également être modifiés avec la fonction set builtin :

#!/bin/sh

printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"

$ ./set-args a b c d e      # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X