Mam skrypt w pliku o nazwie wystąpienie:
echo "hello world"
echo ${1}
A kiedy uruchamiam ten skrypt za pomocą:
./instance solfish
Otrzymuję ten wynik:
hello world
solfish
Ale kiedy biegnę:
echo $#
Mówi „0”. Czemu? Nie rozumiem, co $#
to znaczy.
Proszę wyjaśnij to.
$#
? Co chcesz osiągnąć Skąd masz to polecenie? To w ogóle nie ma znaczenia.echo $#
i wrócił,0
co jest normalne. Zaskoczyło Cię to, ale nie wyjaśniłeś, czego się spodziewałeś ani dlaczego. Pomoże nam to udzielić lepszej odpowiedzi, jeśli wyjaśnisz, czego się spodziewałeś. Co myślałeś, że toecho $#
by zrobiło. Gdybyś uciekał./instance solfish
i./instance
zawierałecho $#
, to by to wydrukowało,1
a nie0
.Odpowiedzi:
$#
jest specjalną zmienną wbash
, która rozwija się do liczby argumentów (parametrów pozycyjnych) tj.$1, $2 ...
przekazywanych do danego skryptu lub powłoki w przypadku argumentów przekazywanych bezpośrednio do powłoki npbash -c '...' ....
. w .Jest to podobne do
argc
w C.Być może to wyjaśni:
Zauważ, że
bash -c
pobiera argument po następującej po nim komendzie, zaczynając od 0 ($0
; technicznie jest to po prostubash
sposób na ustawienie$0
, a nie argument tak naprawdę), więc_
jest tutaj używany jako symbol zastępczy; rzeczywistymi argumentami sąx
($1
),y
($2
) iz
($3
).Podobnie w twoim skrypcie (zakładając
script.sh
), jeśli masz:Kiedy to zrobisz:
skrypt wyświetli 2; również,
wyświetli 1.
źródło
bash -c
zachowanie jest inne niż w przypadku uruchamiania wykonywalnego skryptu powłoki, ponieważ w tym drugim przypadku argument o indeksie 0 jest poleceniem powłoki używanym do jego wywołania. Jako taki, myślę, że sposobem na poprawienie tej odpowiedzi jest zmiana jej wykonywania skryptów jako plików zamiast używaniabash -c
, ponieważ w ten sposób pytający to robił.$0
byłby sam skrypt; byłyby argumenty$1, $2, $3...
.bash -c
zachowanie jest inne, ponieważ jest przeznaczone do użytku nieinteraktywnego, a argumenty następujące po poleceniu zaczną się$0
, o czym wyraźnie wspomniałem.bash -c
, powinieneśbash
podać jakąś znaczącą nazwę jako wypełniacz dla 0. arg.bash -c 'echo "$@"' foo bar
drukuje tylkobar
, ponieważ"$@"
nie obejmuje$0
, tak jak zawsze.bash -c
nie „make $ 0 jeden z argumentami”, a jedynie pozwala na ustawienie „$ 0” w taki sam sposób, gdy uruchomiony program z tejexecve
funkcji systemowej lub jakikolwiek sposób płaszcza przesłanianie 0TH arg.$0
nigdy nie powinien być uważany za „jeden z argumentów”.echo $#
wyświetla liczbę parametrów pozycyjnych skryptu.Nie masz, więc wyprowadza 0.
echo $#
jest przydatny w skrypcie, a nie jako osobne polecenie.Jeśli uruchomisz skrypt z niektórymi parametrami, takimi jak
echo $#
umieszczane w skryptu pokaże na wyjściu 2.źródło
echo $#
do skryptu i uruchomisz ponownie./instance solfish
, powinieneś otrzymać dodatkową linię wyjściową,1
ponieważ podałeś 1 parametr$#
jest zwykle używany w skryptach bash, aby zapewnić przekazanie parametru. Ogólnie rzecz biorąc, sprawdzasz parametr na początku skryptu.Oto na przykład fragment skryptu, nad którym dzisiaj pracowałem:
Podsumowując
$#
raporty, liczba parametrów przekazanych do skryptu. W twoim przypadku nie przekazałeś żadnych parametrów, a raportowany wynik to0
.Inne
#
zastosowania w Bash#
Jest często używany w bash policzyć liczbę wystąpień lub długość zmiennej.Aby znaleźć długość łańcucha:
zwraca:
11
Aby znaleźć liczbę elementów tablicy:
zwraca:
3
Aby znaleźć długość pierwszego elementu tablicy:
zwraca:
1
(DługośćA
0 jest pierwszym elementem, ponieważ tablice używają zerowych indeksów / indeksów).źródło
$# -ne 1
? Dlaczego nie$# -le 0
lub równoważny?$#
to liczba argumentów, ale pamiętaj, że będzie różna w funkcji.$#
to liczba parametrów pozycyjnych przekazanych do skryptu, powłoki lub funkcji powłoki . Jest tak, ponieważ podczas działania funkcji powłoki parametry pozycyjne są tymczasowo zastępowane argumentami funkcji . Pozwala to funkcjom akceptować i wykorzystywać własne parametry pozycyjne.Ten skrypt zawsze drukuje
3
, niezależnie od liczby argumentów przekazanych do samego skryptu, ponieważ"$#"
w funkcjif
rozwija się do liczby argumentów przekazanych do funkcji:Jest to ważne, ponieważ oznacza to, że taki kod nie działa zgodnie z oczekiwaniami, jeśli nie znasz sposobu działania parametrów pozycyjnych w funkcjach powłoki:
In
check_args
,$#
rozwija się do liczby argumentów przekazanych samej funkcji, która w tym skrypcie ma zawsze wartość 0.Jeśli chcesz taką funkcjonalność w funkcji powłoki, musisz zamiast tego napisać coś takiego:
Działa
$#
to, ponieważ jest rozszerzone poza funkcję i przekazane do funkcji jako jeden z jej parametrów pozycyjnych. Wewnątrz funkcji$1
rozwija się do pierwszego parametru pozycyjnego, który został przekazany do funkcji powłoki, a nie do skryptu, którego jest częścią.Tak więc, jak
$#
, specjalne parametry$1
,$2
itp, jak$@
i$*
również odnosić się do argumentów przekazywanych do funkcji, gdy są one w rozbudowanych funkcji. Jednakże,$0
nie nie zmieni się nazwa funkcji, dlatego byłem jeszcze w stanie wykorzystać go do produkcji komunikat o błędzie jakości.Podobnie, jeśli zdefiniujesz jedną funkcję w drugiej, pracujesz z parametrami pozycyjnymi przekazanymi do najbardziej wewnętrznej funkcji, w której przeprowadzane jest rozwinięcie:
Wywołałem ten skrypt
nested
i (po uruchomieniuchmod +x nested
) uruchomiłem go:Tak, wiem. „1 argumenty” to błąd pluralizacji.
Parametry pozycyjne można również zmienić.
Jeśli piszesz skrypt, parametrami pozycyjnymi poza funkcją będą argumenty wiersza poleceń przekazywane do skryptu, chyba że je zmieniłeś .
Jednym z powszechnych sposobów ich zmiany jest
shift
wbudowane, które przesuwa każdy parametr pozycyjny w lewo o jeden, upuszczając pierwszy i zmniejszając$#
o 1:Można je również zmienić za pomocą
set
wbudowanego:źródło