Są to zmienne w powłoce jak $0
, $1
, $2
, $?
, itd.
Próbowałem wydrukować powłokę i zmienne środowiskowe za pomocą następującego polecenia:
set
Ale tych zmiennych nie było na liście.
Zasadniczo te zmienne nie są uważane za zmienne powłoki / środowiska, prawda? (nawet jeśli je wyprowadzasz, musisz poprzedzić je znakiem $
, podobnie jak w przypadku zmiennych powłoki / środowiska)
export 3
zmienić się$3
w zmienną środowiskową. Nie możeszunset 3
; i nie można przypisać$3
nowej wartości za pomocą3=val
.Odpowiedzi:
Zmienne są jedną z trzech różnych odmian parametrów w powłoce.
_
litery lub litery, po której następuje zero lub więcej liter, cyfr lub_
.$1
,$2
...$0
tym wszystkie są różnymi znakami interpunkcyjnymi.set
wyświetla tylko zmienne powłoki.Podzbiorem zmiennych powłoki są zmienne środowiskowe, których wartości są albo dziedziczone ze środowiska podczas uruchamiania powłoki, albo są tworzone przez ustawienie
export
atrybutu na prawidłową nazwę.źródło
set
wyświetla wszystkie parametry wzsh
(nie $ 1, 2 $ ... ale $ *, $ @) oraz funkcje w bash i bosh. Niektóre powłoki, takie jak ksh93 i starsze wersje kreskowych zmiennych wyjściowych env, które nie zostały zmapowane na zmienne powłoki. (env 1=foo ksh -c set
drukuje się1=foo
)Zmienne środowiskowe a parametry pozycyjne
Zanim zaczniemy omawiać
$INTEGER
typy zmiennych, musimy zrozumieć, czym one naprawdę są i czym różnią się od zmiennych środowiskowych. Zmienne takie jak$INTEGER
nazywane są parametrami pozycyjnymi. Jest to opisane w standardzie POSIX (Portable Operating System Interface), sekcja 2.1 (wyróżnienie moje):Natomiast zmienne takie jak
$HOME
i$PATH
są zmiennymi środowiskowymi. Ich definicja jest opisana w rozdziale 8 normy :Zwróć uwagę na ich opis. Parametry pozycyjne mają pojawiać się przed poleceniem, tj
command positional_arg_1 positional_arg_2...
. Są one przeznaczone do dostarczenia przez użytkownika, aby powiedział polecenie, co konkretnie zrobić. Kiedy to zrobiszecho 'Hello' 'World'
, wydrukuje ciągiHello
iWorld
, ponieważ są to parametry pozycyjne dlaecho
- rzeczy, na których chceszecho
operować. Iecho
jest zbudowany w taki sposób, że rozumie parametry pozycyjne jako ciągi znaków do wydrukowania (chyba że są jedną z opcjonalnych flag takich jak-n
). Jeśli zrobisz to z innym poleceniem, może nie zrozumieć, coHello
iWorld
to dlatego, że może oczekuje liczby. Zauważ, że parametry pozycyjne nie są „dziedziczone” - proces potomny nie wie o parametrach pozycyjnych elementu nadrzędnego, chyba że zostanie jawnie przekazany do procesu potomnego. Często widzisz parametry pozycyjne przekazywane za pomocą skryptów otoki - tych, które mogą sprawdzać, czy istnieje już instancja polecenia lub dodawać dodatkowe parametry pozycyjne do rzeczywistego polecenia, które zostanie wywołane.Natomiast zmienne środowiskowe mają wpływać na wiele programów. Są to zmienne środowiskowe , ponieważ są ustawione poza samym programem (więcej na ten temat poniżej). Niektóre zmienne środowiskowe, takie jak
HOME
lubPATH
mają określony format, konkretne znaczenie i będą oznaczały to samo dla każdego programu.HOME
zmienna będzie oznaczać to samo dla zewnętrznego narzędzia, takiego jak dla/usr/bin/find
twojej powłoki (aw konsekwencji dla skryptu) - jest to katalog domowy nazwy użytkownika, pod którym działa proces. Zauważ, że na przykład zmienne środowiskowe mogą służyć do uwzględnienia określonego zachowania poleceniaUID
zmiennej środowiskowej można użyć do sprawdzenia, czy skrypt działa z uprawnieniami administratora, czy też nie, i odpowiednio rozgałęzić do określonych akcji. Zmienne środowiskowe są dziedziczone - procesy potomne otrzymują kopię środowiska rodzica. Zobacz także Jeśli procesy dziedziczą środowisko rodzica, dlaczego potrzebujemy eksportu?Krótko mówiąc, główne rozróżnienie polega na tym, że zmienne środowiskowe są ustawiane poza poleceniem i nie powinny być zmieniane (zwykle), podczas gdy parametry pozycyjne to rzeczy, które mają być przetwarzane przez polecenie i zmieniają się.
Nie tylko koncepcje powłoki
W komentarzach zauważyłem, że mieszasz terminal i powłokę i naprawdę polecam przeczytanie o prawdziwych terminalach, które kiedyś były urządzeniami fizycznymi. W dzisiejszych czasach „terminal”, do którego zwykle się odnosimy, to okno z czarnym tłem i zielonym tekstem jest w rzeczywistości oprogramowaniem, procesem. Terminal to program, który uruchamia powłokę, podczas gdy powłoka jest także programem, który odczytuje to, co wpisujesz, aby wykonać (to znaczy, jeśli jest to powłoka interaktywna; powłoki nieinteraktywne to skrypty i
sh -c 'echo foo'
typy wywołań). Więcej o muszlach tutaj .Jest to ważne rozróżnienie, ale także ważne, aby uznać, że terminal jest programem i dlatego przestrzega tych samych reguł środowiska i parametrów pozycyjnych. Twoje
gnome-terminal
po uruchomieniu spojrzy na twojąSHELL
zmienną środowiskową i stworzy dla ciebie odpowiednią domyślną powłokę, chyba że podasz inne polecenie-e
. Powiedzmy, że zmieniłem domyślną powłokę naksh
- gnome-terminalksh
zamiast tego odrodzi siębash
. To także przykład wykorzystania środowiska przez programy. Gdybym wyraźnie powiedziećgnome-terminal
ze-e
uruchomić specyficzną otoczkę - będzie to zrobić, ale to nie będzie trwały. Natomiast środowisko ma być w większości niezmienione (więcej na ten temat później).Jak widać, zmienne środowiskowe i pozycyjne są właściwościami procesu / polecenia, a nie tylko powłoki. Jeśli chodzi o skrypty powłoki, postępują one zgodnie z modelem ustawionym przez język programowania C. Weźmy na przykład funkcję C,
main
która zazwyczaj wygląda, gdzie
argc
jest liczba argumentów wiersza polecenia iargv
efektywnie tablica parametrów wiersza polecenia, a następnie jestenviron
funkcja (w Linuksie, któraman -e 7 environ
), aby uzyskać dostęp do takich rzeczy, jak ścieżka katalogu domowego użytkownika, lista katalogów, wPATH
których możemy szukać plików wykonywalnych itp. Skrypty powłoki są również modelowane w podobny sposób. W terminologii powłoki mamy parametrów pozycyjnych$1
,$2
i tak dalej, podczas gdy$#
wiele parametrów pozycyjnych. Co$0
? To jest nazwa samego pliku wykonywalnego, który również jest modelowany z języka programowania C -argv[0]
będzie to nazwa twojego „pliku wykonywalnego”. Dotyczy to w większości języków programowania i skryptów .Powłoki interaktywne a nieinteraktywne
Jedną z rzeczy, o których już wspomniałem, jest rozróżnienie między powłokami interaktywnymi i nieinteraktywnymi . Monit, w którym wpisujesz polecenia - jest interaktywny, wchodzi w interakcję z użytkownikiem. Natomiast gdy masz skrypt powłoki lub uruchamiasz go
bash -c''
w sposób nieinteraktywny.I tu właśnie ważne staje się rozróżnienie. Powłoka jest uruchomienie już jest procesem, który zrodził się z parametrów pozycyjnych (na
bash
powłokę logowania jest jeden „... którego pierwszy znak argumentu jest zerowy. - lub jeden uruchomiono z opcją --login” ( odniesienie ) )Natomiast skrypty i powłoki uruchamiane z
-c
opcją mogą korzystać z argumentów$1
i$2
argumentów. Na przykład,Zauważ, że też
sh
tam użyłem , ponieważ małe dziwactwo-c
opcji polega na przyjęciu pierwszego parametru pozycyjnego i przypisaniu go$0
, w przeciwieństwie do typowej nazwy programu.Inną rzeczą, na którą należy zwrócić uwagę, jest to, że parametry pozycyjne nazywam „ramkami”. Zauważ, że najpierw uruchomiliśmy
bash
z własnymi parametrami pozycyjnymi, ale te parametry pozycyjne stały się parametrami doecho
istat
. I każdy program rozumie to na swój sposób. Gdybyśmy podalistat
ciągHello World
i nie ma plikuHello World
, spowodowałby to błąd;bash
traktuje go jak zwykły ciąg, alestat
oczekuje, że będzie to istniejąca nazwa pliku. Natomiast wszystkie programy zgodziłyby się, że zmienna środowiskowaHOME
jest katalogiem (chyba że programista zakodował ją w nieuzasadniony sposób).Czy możemy sobie poradzić ze zmiennymi środowiskowymi i parametrami pozycyjnymi?
Technicznie rzecz biorąc, możemy sobie poradzić z obydwoma, ale nie powinniśmy bawić się zmiennymi środowiskowymi, podczas gdy często musimy podawać parametry pozycyjne. Możemy uruchamiać polecenia w powłoce z przygotowaniem zmiennej, na przykład:
Możemy również umieszczać zmienne w środowisku, korzystając
export variable=value
z powłoki lub skryptu. Lub możemy uruchomić polecenie z całkowicie pustym środowiskiem za pomocąenv -c command arg1 arg2
. Zazwyczaj jednak nie zaleca się manipulowania środowiskiem, szczególnie przy użyciu dużych liter lub zastępowania już istniejących zmiennych środowiskowych. Zauważ, że jest to zalecane, choć nie jest standardem.W przypadku parametrów pozycyjnych sposób ich ustawiania jest oczywisty, po prostu dodaj je do polecenia, ale są też sposoby, aby ustawić je w inny sposób , a także zmienić listę tych parametrów za pomocą
shift
polecenia.Podsumowując, cel tych dwóch celów jest inny i istnieją one z jakiegoś powodu. Mam nadzieję, że ludzie uzyskali wgląd w tę odpowiedź i fajnie było ją przeczytać, tak jak dla mnie napisanie tej odpowiedzi.
Uwaga dotycząca polecenia set
set
Rozkaz, zgodnie z instrukcją zachowuje się jak w przykładzie (od instrukcji bash nacisk dodano):Innymi słowy,
set
analizuje zmienne specyficzne dla powłoki, z których niektóre znajdują się na przykład w środowiskuHOME
. Dla kontrastu polecenia takie jakenv
iprintenv
spójrz na rzeczywistą zmienną środowiskową, z którą działa polecenie. Zobacz także to .źródło
1="foo"
ale później dowiedziałem się, że według definicji POSIX „słowo” (czyli nazwa obiektu takiego jak zmienna lub funkcja) nie może się rozpocząć z cyfrą (patrz pytanie, które opublikowałem na ten temat ). Parametry pozorne najwyraźniej stanowią wyjątek od tej reguły.$1
,$2
i tak dalej, w interaktywnej powłoce, w rzeczywistości odbywa się to za pomocąset
polecenia, często w celu obejścia/bin/sh
ograniczenia braku macierzy. Dziękuję za zwrócenie mi na to uwagi. Zamierzam również edytować odpowiedź w ciągu najbliższych kilku dni, ponieważ wymaga ona trochę dodatkowego dopracowania i aktualizacji.conda
po uruchomieniusource conda/bin/activate
, to sprawdza, czy$1
,$2
itp, są ustawione, w celu ustalenia, czy został uruchomiony jako skrypt z argumentów lub nie. To kończy się zerwaniem w systemach, które z jakiegoś powodu mają te ustawione w środowisku interaktywnym. Mam nadzieję dowiedzieć się, czy to niestandardowe zachowanie jest wadą w systemie do ustawiania tych zmiennych w środowisku interaktywnym, czy w programie do używania ich do określania, czy zostało uruchomione jako skrypt.conda
programistów lub każdego, kto jest oryginalnym autorem takiego skryptu, ponieważ sprawdzanie${N}
parametrów jest zdecydowanie niewłaściwą drogą. Istnieją pytania na ten sam temat tutaj i tutaj , a mniej więcej przenośny sposób polega na sprawdzeniu, czy${0}
jest taki sam jak nazwa skryptu, podczas gdybash
faktycznie ma do tego celu zmienną środowiskowąTe
$1, $2, $3, ..., ${10}, ${11}
zmienne nazywane są parametry pozycyjne i są ujęte w sekcji ręcznego bash3.4.1
Jeśli chodzi o
$?
i$0
, te specjalne parametry są omówione w następnej sekcji3.4.2
źródło
$1
,$2
... są parametrami pozycyjnymi , nie są zmiennymi, a tym bardziej zmiennymi środowiskowymi.Bourne jak powłoki terminologii
$something
nazywa parametrów ekspansji (obejmuje również${something#pattern}
i więcej w pewnych pocisków, takich jak${array[x]}
,${param:offset}
,${x:|y}
i wielu operatorów więcej rozszerzeń).Istnieją różne rodzaje parametrów:
$foo
,$PATH
$1
,$2
... argumenty otrzymane przez twój skrypt)$0
,$-
,$#
,$*
,$@
,$$
,$!
,$?
...nazwy zmiennych w powłokach podobnych do Bourne'a muszą zaczynać się od jednego znaku alfabetycznego (dowolnego rozpoznawanego przez ustawienia regionalne lub ograniczonego do a-zA-Z w zależności od powłoki) i podkreślenia, a następnie zero lub więcej znaków alfanumerycznych lub podkreślników.
W zależności od powłoki zmienne mogą mieć różne typy (skalarne, tablicowe, mieszające) lub mieć określone atrybuty (tylko do odczytu, eksportowane, małe litery ...).
Niektóre z tych zmiennych są tworzone przez powłokę lub mają specjalne znaczenie dla powłoki (jak
$OPTIND
,$IFS
,$_
...)Zmienne powłoki, które mają atrybut eksportu, są automatycznie eksportowane jako zmienne środowiskowe do poleceń wykonywanych przez powłokę.
Zmienna środowiskowa jest pojęciem odrębnym od zmiennych powłoki. Eksportowanie zmiennej powłoki nie jest jedynym sposobem przekazania zmiennej środowiskowej do wykonania polecenia.
przekaże
VAR
zmienną środowiskową doprintenv
polecenia (które chcemy wydrukować jego zawartość), ale możesz także:lub:
na przykład.
Zmienne środowiskowe mogą mieć dowolną nazwę (mogą zawierać dowolny znak, ale
=
mogą być nawet puste). Nadanie zmiennej środowiskowej nazwy, która nie jest zgodna z nazwą zmiennej powłoki podobnej do Bourne'a, nie jest dobrym pomysłem, ale jest to możliwe:Powłoki będą mapować otrzymywane zmienne środowiskowe na zmienne powłokowe tylko dla tych zmiennych środowiskowych, których nazwy są poprawnymi zmiennymi powłokowymi (aw niektórych powłokach ignorują niektóre specjalne, takie jak
$IFS
).Tak więc, podczas gdy będziesz mógł przekazać
1
zmienną środowiskową do polecenia:Nie oznacza to, że wywołanie powłoki za pomocą tej zmiennej środowiskowej ustawiłoby wartość
$1
parametru:źródło
Nie, są to parametry skryptu. Na przykład, jeśli wywołasz skrypt, na przykład:
następnie w skrypcie będą dostępne te parametry jako
a $ 0 to nazwa samego skryptu.
Więc kiedy jesteś poza skryptem, te zmienne nie są dostępne (oprócz 0 $, które wyświetla / bin / bash - sama powłoka).
źródło
$0
będzie wskazywał na twój aktualny proces terminalowy (prawdopodobnie bash) i$?
jest po prostu kodem zakończenia ostatniego procesu.gnome-terminal
z argumentami (gnome-terminal Hello World
). Widziałem$0
, ale nie widziałem$1
i$2
.