Powiedzmy, że wyeksportowałem zmienną:
foo=bar
export foo
Teraz chciałbym go wyeksportować. To znaczy, jeśli nie, sh -c 'echo "$foo"'
nie powinienem bar
. foo
w ogóle nie powinien pojawić się w sh -c
środowisku.
sh -c
jest jedynie przykładem, łatwym sposobem na pokazanie obecności zmiennej. Poleceniem może być cokolwiek - może to być coś, na którego zachowanie wpływa po prostu obecność zmiennej w jej otoczeniu.
Mogę:
unset
zmienną i zgub ją- Usuń go za pomocą
env
każdego polecenia:env -u foo sh -c 'echo "$foo"'
- niepraktyczne, jeśli chcesz nadal używać bieżącej powłoki.
Idealnie chciałbym zachować wartość zmiennej, ale nie pokazywać jej wcale w procesie potomnym, nawet jako pustej zmiennej.
Chyba mógłbym zrobić:
otherfoo="$foo"; unset foo; foo="$otherfoo"; unset otherfoo
Grozi to tupnięciem otherfoo
, jeśli już istnieje.
Czy to jedyny sposób? Czy są jakieś standardowe sposoby?
mktemp
jeśli jest on wystarczająco przenośny, i rozbroić wartość, a następnie pobrać plik tymczasowy, aby przypisać zmienną. Można utworzyć przynajmniej plik tymczasowy o mniej więcej dowolnej nazwie w przeciwieństwie do zmiennej powłoki.sh -c
Polecenie jest jedynie przykładem. Wykonaj dowolne polecenie, w ramach którego nie możesz rozbroić zmiennej zamiast niej.Odpowiedzi:
Nie ma standardowego sposobu.
Można uniknąć używania zmiennej tymczasowej za pomocą funkcji. Poniższa funkcja dba o to, aby nieuzbrojone zmienne nieuzbrojone i puste zmienne puste. Nie obsługuje jednak funkcji znalezionych w niektórych powłokach, takich jak zmienne tylko do odczytu lub zmienne typowane.
W ksh, bash i zsh możesz wyeksportować zmienną za pomocą
typeset +x foo
. Zachowuje to specjalne właściwości, takie jak typy, więc lepiej go używać. Myślę, że wszystkie powłoki, które majątypeset
wbudowane, majątypeset +x
.źródło
${var+foo}
, ocenia,foo
czyvar
jest ustawiony, nawet jeśli pusty, i nic innego.typeset +x
vsexport -n
dla powłok, które obsługują te pierwsze? Jestexport -n
rzadszy, czy też nie zachowuje niektórych właściwości?export -n
lubtypeset +x
obojętnie. W ksh lub zsh jest tylkotypeset +x
.EDIT: W przypadku
bash
tylko, jak wskazano w komentarzach:-n
Opcjaexport
usuwaexport
nieruchomość z każdej podanej nazwie. (Patrzhelp export
.)Więc dla
bash
, komenda chcesz to:export -n foo
źródło
Napisałem podobną funkcję POSIX, ale nie ryzykuje to wykonania dowolnego kodu:
Będzie również obsługiwał tyle argumentów, ile chcesz. Jeśli argument jest prawidłową nazwą, która nie jest jeszcze ustawiona, jest dyskretnie ignorowany. Jeśli argument jest złą nazwą, zapisuje go do stderr i zatrzymuje odpowiednio, chociaż każda poprawna nazwa poprzedzająca niepoprawną w wierszu poleceń będzie nadal przetwarzana.
Myślałem o innym sposobie. Bardziej mi się podoba.
Oba wykorzystują wiele takich samych technik. Zasadniczo, jeśli zmienna powłoki jest rozbrojona, odniesienie do niej nie będzie rozszerzane wraz z
+
rozszerzaniem parametrów. Ale jeśli jest ustawiony - niezależnie od jego wartości - rozszerzenie parametru takie jak:${parameter+word}
zostanie rozwinięte doword
- a nie do wartości zmiennej. Tak więc zmienne powłoki wykonują autotest i zastępują się sukcesem.Mogą również zawieść . W górnej funkcji, jeśli zostanie znaleziona zła nazwa, przechodzę
$1
do$2
i pozostawiam$1
null, ponieważ następną rzeczą, którą robię, jest alboreturn
sukces, jeśli wszystkie argumenty zostały przetworzone i pętla jest na końcu, lub, jeśli argument był nieprawidłowy, powłoka będzie rozwiń,$2
w$1:?
który zabije skryptowaną powłokę i zwróci przerwanie do interaktywnej podczas pisaniaword
do stderr.W drugim
getopts
wykonuje się zadania. I nie przypisuje złej nazwy - raczej napisz, wypisze standardowy komunikat o błędzie do stderr. Co więcej, zapisuje wartość arg,$OPTARG
jeśli argument był w pierwszej kolejności nazwą zmiennej ustawionej. Po zrobieniugetopts
wszystko, co jest potrzebne, to rozszerzenieeval
zestawuOPTARG
do odpowiedniego zadania.źródło
export
uzyskać dziwne imię, nie zabije twojego komputera.var=something; varname=var; export "$varname"
jest całkowicie poprawny. to samo dotyczyunset
, a wraz z tym i drugim, ale gdy tylko zawartość tej"$varname"
zmiennej oszaleje, może być to godne pożałowania. i tak właśnie siębash
stało, że i tak nastąpił ten błąd eksportu całej funkcji.