Użycie ^ jako metaznaku powłoki

19

Napisałem dzisiaj mały skrypt, który zawierał

grep -q ^local0 /etc/syslog.conf

Podczas przeglądu współpracownik zasugerował, aby ^local0go zacytować, ponieważ ^oznacza „fajkę” w powłoce Bourne'a. Zaskoczony tym twierdzeniem, próbowałem wyśledzić wszelkie odniesienia, które o tym wspominały. Nic, co znalazłem w Internecie, nie sugerowało, że to był problem.

Okazuje się jednak, że implementacja bsh(która twierdzi, że jest powłoką Bourne'a) w systemie AIX 7 faktycznie ma takie zachowanie:

> bsh
$ ls ^ wc
      23      23     183
$ ls | wc
      23      23     183

Żadna z innych implementacji „powłoki Bourne'a”, które próbowałem, nie zachowuje się w ten sposób (to ^znaczy wcale nie jest uważana za metaznak powłoki). Próbowałem shna CentOS (który jest naprawdę bash) i shna FreeBSD (który nie jest bash). Nie mam wielu innych systemów do wypróbowania.

Czy to zachowanie jest oczekiwane? Które pociski uważają ^za metaznak rury?

Greg Hewgill
źródło
1
Wiem, że ^to znak negacji w Zsh, a także w przestrzeni wyrażeń regularnych. W ramach oddzielnego komentarza zaleca się stosowanie pojedynczych cudzysłowów w wyrażeniu grep w celu przenoszenia między powłokami.
mkc
Powłoka bourne miała wiele dziwnych zachowań, które wciąż występują w nowoczesnym kodzie powłoki, np [ x"$foo" = x"bar" ].
Jordan
bshto nie jest Bourne Shell. Nazwa jest nadużywana tylko dla powłoki Bourne Shell tylko w systemie AIX. bshjest raczej powłoką wprowadzoną przeze mnie w 1984 r. w H.Berhold AG na UNOS (pierwszy klon UNIX). Zauważ, że AIX nie istniał w 1984 roku.
schily

Odpowiedzi:

21

^Charakter jako synonim |sięga od skorupy Thompson . Zostały one wprowadzone w tym samym czasie w Uniksie v4 i są wymienione razem na stronie podręcznika . Sven Mascheck wspomina, że ^„prawdopodobnie [wprowadzono] ze względu na wygodę we wczesnych terminalach z dużymi literami ”, gdzie pisanie |było „nieco uciążliwe” .

Powłoka Thompsona dawno już minęła, ale następca powłoki Bourne zachował tę samą składnię (mimo że strona podręcznika wspomina tylko |).

Pociski następcy, takie jak ash, bash i ksh, rozumieją tylko |jako znak potoku. Nie znajdziesz prawdziwej powłoki Bourne'a w wariantach unixowych Open Source, ponieważ przez długi czas nie było wydania otwartej wersji powłoki Bourne'a. (Myślę, że OpenSolaris zawierał jeden, ale nie został przyjęty gdzie indziej, ponieważ do tego czasu był już przestarzały przez nowsze implementacje).

Specyfikacja Single Unix nie wspomina ^o znaku specjalnym, co oznacza, że ​​powłoki POSIX powinny ją interpretować dosłownie¹. Nie sądzę, żeby kiedykolwiek istniał w pełni zgodny z POSIX wariant powłoki Bourne'a (tylko niezależne implementacje).

^jest specjalny w zsh, gdy opcja extendedglobjest włączona, ale nie w trybie zgodności sh. W trybie domyślnym różni się od POSIX na wiele sposobów.

W ^każdym razie polecam cytowanie wyrażenia regularnego. Cytuj wyrażenie regularne w skrypcie, niezależnie od tego, jakie znaki się w nim pojawiają.

¹ Z wyjątkiem pierwszego znaku wyrażenia nawiasowego we wzorze wieloznacznym, gdzie !jest standardowym znakiem negacji, ale implementacje mogą również interpretować ^w ten sam sposób.

Gilles „SO- przestań być zły”
źródło
Dzięki, ten cały wątek TUHS z 2003 roku był pouczający.
Greg Hewgill
Dla kompletności możesz wspomnieć, że ^jest to wyjątkowe, fishgdy jest operatorem przekierowania, rc/ esgdzie jest operatorem konkatenacji , lub csh / tcsh / bash / zsh do ekspansji historii, gdy jest to pierwszy znak wiersza poleceń.
Stéphane Chazelas 18.04.16
3

Tak, OpenSolaris zawiera źródło Bourne Shell, ale to źródło nie jest przenośne.

Utrzymywana i wysoce przenośna wersja źródła Bourne Shell znajduje się tutaj w schily-*.tar.bz2archiwach.

Oto pokrewna część źródła w cmd.c:

/* 
* ^ is a relic from the days of UPPER CASE ONLY tty model 33s 
*/ 
if ((t = item(TRUE)) != 0 && (wdval == '^' || wdval == '|')) 

Widzisz, nie jest to związane z konkretną powłoką (np. Powłoką Thompsona), ale z faktem, że w latach 70. XX wieku wciąż istniały tylko wielkie litery.

schily
źródło