Czy istnieje sposób na source
skrypt powłoki w przestrzeń nazw, najlepiej skrypt powłoki bash, ale sprawdziłbym inne powłoki, gdyby miały tę funkcję, a bash nie.
Rozumiem przez to, na przykład, coś w rodzaju „przedrostek wszystkich zdefiniowanych symboli czymś, aby nie kolidowały z już zdefiniowanymi symbolami (nazwy zmiennych, nazwy funkcji, aliasy)” lub jakiekolwiek inne narzędzie, które zapobiega kolizji nazw.
Jeśli istnieje rozwiązanie, w którym mogę jednocześnie używać przestrzeni nazw source
( NodeJS
styl), byłoby to najlepsze.
Przykładowy kod:
$ echo 'hi(){ echo Hello, world; }' > english.sh
$ echo 'hi(){ echo Ahoj, světe; }' > czech.sh
$ . english.sh
$ hi
#=> Hello, world
$ . czech.sh #bash doesn't even warn me that `hi` is being overwritten here
$ hi
#=> Ahoj, světe
#Can't use the English hi now
#And sourcing the appropriate file before each invocation wouldn't be very efficient
( easiest thing ever )
. Ale nie do końca tego szukasz. Myślę, że możesz to zrobić,( stuff in subshell; exec env ) | sed 's/^/namespace_/'
aeval
wynik w powłoce nadrzędnej, ale to trochę nieprzyjemne.ksh93
. Przestrzenie nazw są dla niego fundamentalne - a wszystkie typy nazw (które można również wpisać) obsługują przestrzeń nazw. Jest także znacznie szybszy praktycznie pod każdym względem niżbash
, nawiasem mówiąc,.env | sed ...
działałoby dla zmiennych, mógłbym zrobić,set
aby uzyskać funkcje, ale wyszukiwanie i zamiana byłyby problemem - funkcje mogą się nawzajem wywoływać, więc trzeba zastąpić wszystkie wywołania krzyżowe prefiksami krzyżowymi, ale bez zamiany te same słowa w innym miejscu w kodzie definicji funkcji, gdzie nie jest to wywołanie. Do tego potrzebny byłby parser bash, a nie tylko wyrażenie regularne, i nadal działałby tylko tak długo, jak długo funkcje nie wywoływałyby się przez eval.Odpowiedzi:
Z
man ksh
systemu zksh93
zainstalowanym ...Aby zademonstrować, oto koncepcja zastosowana do przestrzeni nazw zapewnionej domyślnie dla każdej zwykłej zmiennej powłoki przypisanej w
ksh93
powłoce. W poniższym przykładzie zdefiniujędiscipline
funkcję, która będzie działać jako przypisana.get
metoda dla$PS1
zmiennej powłoki. Każda zmienna powłoki zasadzie dostaje swoją własną przestrzeń nazw z, co najmniej, domyślnyget
,set
,append
orazunset
metody. Po zdefiniowaniu następującej funkcji, za każdym razem, gdy zmienna$PS1
jest przywoływana w powłoce, dane wyjściowedate
zostaną narysowane u góry ekranu ...(Zwróć również uwagę na brak
()
podpowłoki w powyższym zastąpieniu polecenia)Technicznie, przestrzenie nazw i dyscypliny nie są dokładnie tym samym (ponieważ dyscypliny można zdefiniować tak, aby stosowały się globalnie lub lokalnie do konkretnej przestrzeni nazw ) , ale są one nieodłączną częścią konceptualizacji podstawowych typów danych powłoki
ksh93
.Aby zająć się konkretnymi przykładami:
...lub...
źródło
Pisałem funkcję powłoki POSIX, które mogą być używane do lokalnego obszaru nazw wbudowanym poleceniem powłoki lub funkcji w dowolnym z
ksh93
,dash
,mksh
, lubbash
(o nazwie specjalnie bo osobiście potwierdził go do pracy w każdym z nich) . Spośród powłok, w których go testowałem, nie spełnił on moich oczekiwańyash
i nigdy nie spodziewałem się, że zadziałazsh
. Nie testowałemposh
. Dawno temu zrezygnowałem z jakiejkolwiek nadzieiposh
i od jakiegoś czasu jej nie instalowałem. Może to działa wposh
...?Mówię, że jest to POSIX, ponieważ czytając specyfikację, korzysta ona z określonego zachowania podstawowego narzędzia, ale, co prawda, specyfikacja jest pod tym względem niejasna i przynajmniej jedna osoba najwyraźniej się ze mną nie zgadza. Ogólnie nie zgadzałem się z tym, w końcu uznałem, że błąd jest mój, i być może również tym razem się mylę co do specyfikacji, ale kiedy go przesłuchałem, nie odpowiedział.
Jak już powiedziałem, to zdecydowanie działa w wyżej wymienionych powłokach i działa w zasadzie w następujący sposób:
command
Komenda jest określony jako w zasadzie dostępne narzędzia oraz z poprzednich$PATH
„d poleceń wbudowanych. Jedną z jego określonych funkcji jest zawijanie specjalnych wbudowanych narzędzi we własnym środowisku podczas ich wywoływania, a więc ...... zachowanie obu powyższych przypisań wiersza poleceń jest poprawne według specyfikacji. Zachowanie obu warunków błędu jest również poprawne i jest w rzeczywistości bardzo prawie całkowicie skopiowane ze specyfikacji. Przypisania poprzedzone wierszami poleceń funkcji lub specjalnych wbudowanych funkcji mają wpływ na bieżące środowisko powłoki. Podobnie błędy przekierowania są określane jako krytyczne, gdy zostaną wskazane na jeden z nich.
command
jest określony, aby wykluczyć specjalne traktowanie specjalnych funkcji wbudowanych w tych przypadkach, a przypadek przekierowania jest faktycznie zademonstrowany przez przykład w specyfikacji.command
Z drugiej strony, zwykłe wbudowane opcje działają w środowisku podpowłoki - co niekoniecznie oznacza proces innego procesu , po prostu powinno być zasadniczo nierozróżnialne. Rezultaty wywołania zwykłego wbudowanego powinny zawsze przypominać to, co można uzyskać z podobnie zdolnego$PATH
polecenia. A więc...Ale
command
polecenie nie może wywoływać funkcji powłoki i dlatego nie może być użyte do wywołania ich specjalnego traktowania, jak to ma miejsce w przypadku zwykłych poleceń wbudowanych. To również zostało określone. W rzeczywistości specyfikacja mówi, że podstawowym narzędziemcommand
jest to, że można jej użyć w ramach funkcji powłoki opakowania o nazwie innej komendy, aby wywołać tę inną komendę bez samoregulacji, ponieważ nie wywoła tej funkcji. Lubię to:Jeśli nie użyjesz
command
go,cd
funkcja prawie na pewno ulegnie awarii dla samoregulacji.Ale jako zwykłe narzędzie wbudowane, które może wywoływać funkcje specjalne,
command
może to robić w środowisku podpowłoki . I tak, podczas gdy aktualny stan powłoki zdefiniowane wewnątrz może przykleić się do bieżącej powłoki - na pewnoread
„s$var1
, a$var2
nie - przynajmniej wyniki Definiuje wiersza polecenia prawdopodobnie nie powinna ...Teraz, czy
command
zdolność do bycia zarówno zwykłym wbudowanym, jak i bezpośrednim wywoływaniem specjalnych wbudowanych jest tylko pewnego rodzaju nieoczekiwaną luką w odniesieniu do definicji wiersza poleceń, nie wiem, ale wiem, że przynajmniej cztery powłoki już wspomniane honorowaćcommand
przestrzeń nazw.I chociaż
command
nie może bezpośrednio wywoływać funkcji powłoki, może wywoływaćeval
tak, jak pokazano, i może to robić pośrednio. Więc zbudowałem opakowanie przestrzeni nazw na tej koncepcji. Wymaga listy argumentów takich jak:... z wyjątkiem tego, że
command
powyższe słowo jest rozpoznawane jako jedno tylko wtedy, gdy można je znaleźć z pustym$PATH
. Poza lokalnie scoping zmienne powłoki nazwane w linii poleceń, ale również lokalnie celownicze wszystkie zmienne z pojedynczymi małymi alfabetycznych nazwisk oraz listę innych standardowych, takich jak$PS3
,$PS4
,$OPTARG
,$OPTIND
,$IFS
,$PATH
,$PWD
,$OLDPWD
i kilka innych.I tak, przez lokalnie Scoping
$PWD
i$OLDPWD
zmienne, a potem wyraźniecd
ING$OLDPWD
i$PWD
może to dość wiarygodnie zakres bieżący katalog roboczy, jak również. Nie jest to gwarantowane, choć bardzo się stara. Zachowuje deskryptor,7<.
a gdy zwróci cel zawijania, robi tocd -P /dev/fd/7/
. Jeśli bieżący katalog roboczy znajdował sięunlink()
w międzyczasie, powinien przynajmniej przynajmniej zdążyć wrócić do niego, ale w tym przypadku wyda brzydki błąd. A ponieważ utrzymuje deskryptor, nie sądzę, że rozsądne jądro powinno pozwolić na odmontowanie urządzenia głównego (???) .Lokalnie wykrywa również opcje powłoki i przywraca je do stanu, w którym je znalazł, gdy wraca zapakowane narzędzie. Traktuje
$OPTS
specjalnie, ponieważ zachowuje kopię we własnym zakresie, który początkowo przypisuje wartość$-
. Po obsłudze wszystkich przypisań w wierszu poleceń zrobi toset -$OPTS
tuż przed wywołaniem celu zawijania. W ten sposób, jeśli zdefiniujesz-$OPTS
w wierszu poleceń, możesz zdefiniować opcje powłoki celu zawijania. Kiedy cel powróci, będzieset +$- -$OPTS
posiadał własną kopię$OPTS
(która nie ma wpływu na definicję wiersza poleceń) i przywróci wszystko do pierwotnego stanu.Oczywiście nic nie powstrzymuje dzwoniącego przed jawnym
returrn
wyjściem z funkcji poprzez cel zawijania lub jego argumenty. Takie postępowanie zapobiegnie przywróceniu / oczyszczeniu stanu, które w innym przypadku byłoby podejmowane.Aby zrobić wszystko, co trzeba, należy przejść trzy
eval
. Najpierw opakowuje się w zasięg lokalny, a następnie od wewnątrz wczytuje argumenty, weryfikuje je pod kątem poprawnych nazw powłok i kończy działanie z błędem, jeśli znajdzie taki, który nie jest. Jeśli wszystkie argumenty są poprawne i ostatecznie jedna spowodujecommand -v "$1"
zwrócenie wartości true (przypomnij:$PATH
w tym momencie jest pusta), toeval
wiersz poleceń zdefiniuje i przekaże wszystkie pozostałe argumenty do celu zawinięcia (choć ignoruje to specjalny przypadekns
- ponieważ to nie będą bardzo przydatne, aeval
głębokość trzech s jest więcej niż wystarczająco głęboka) .Zasadniczo działa tak:
Istnieje kilka innych przekierowania i, a kilka testów dziwne ze sposobem niektóre muszle umieścić
c
w$-
, a następnie odmówić przyjęcia go jako opcjaset
(???) , ale jej wszystko pomocniczy, a przede wszystkim wykorzystywane tylko ocalić od emitującego niechciane wyjście i podobne w przypadkach krawędziowych. I tak to działa. Może to robić, ponieważ ustawia swój własny zasięg lokalny przed wywołaniem owiniętego narzędzia w zagnieżdżonym.Długo, bo staram się tutaj bardzo uważać - trzy
evals
są trudne. Ale dzięki niemu możesz zrobić:Posunięcie się o krok dalej i uporczywe umieszczanie nazw w lokalnym zasięgu zapakowanego narzędzia nie powinno być bardzo trudne. I nawet jak napisano, już definiuje
$LOCALS
zmienną dla opakowanego narzędzia, która składa się tylko z oddzielonej spacjami listy wszystkich nazw, które zdefiniowała w środowisku opakowanego narzędzia.Lubić:
... co jest całkowicie bezpieczne -
$IFS
zostało oczyszczone do wartości domyślnej i wprowadzane są tylko prawidłowe nazwy powłok,$LOCALS
chyba że ustawisz je samodzielnie w wierszu poleceń. I nawet jeśli w zmiennej podzielonej mogą znajdować się znaki globu, można również ustawićOPTS=f
w wierszu polecenia, aby zapakowane narzędzie zabroniło ich ekspansji. W każdym przypadku:A oto funkcja. Wszystkie polecenia mają prefiks w /,
\
aby uniknąćalias
rozszerzeń:źródło