W dokumentacji Perla perlrun (1) sugeruje uruchamianie skryptów Perla przy użyciu dwujęzycznej powłoki / nagłówka Perla:
#!/bin/sh
#! -*-perl-*-
eval 'exec perl -x -wS $0 ${1+"$@"}'
if 0;
Co ${1+"$@"}
znaczy Próbowałem użyć "$@"
zamiast tego (używając Bash jako / bin / sh) i wydaje się, że działa równie dobrze.
Edytować
Dwie odpowiedzi poniżej mówią, że tak powinno być ${1:+"$@"}
. Mam świadomość ${parameter:+word}
składni („Użyj wartości alternatywnej”) udokumentowanej w bash (1). Nie jestem jednak przekonany, ponieważ
Zarówno
${1+"$@"}
i"$@"
działać dobrze, nawet gdy nie ma żadnych parametrów. Jeśli utworzę simple.sh jako#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 "$@"' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
i question.sh as
#!/bin/sh eval 'exec /usr/bin/perl -x -S -- $0 ${1+"$@"}' if 0; #!perl use Data::Dumper; print Dumper(\@ARGV);
Mogę sprawić, by obie pracowały identycznie:
$ ./question.sh $VAR1 = []; $ ./question.sh a $VAR1 = [ 'a' ]; $ ./question.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./question.sh "" $VAR1 = [ '' ]; $ ./simple.sh $VAR1 = []; $ ./simple.sh a $VAR1 = [ 'a' ]; $ ./simple.sh a 'b c' $VAR1 = [ 'a', 'b c' ]; $ ./simple.sh "" $VAR1 = [ '' ];
Korzystają również inne źródła w Internecie
${1+"$@"}
, w tym jeden haker, który zdaje się wiedzieć, co robi.
Być może ${parameter+word}
jest to nieudokumentowana alternatywna (lub przestarzała) składnia ${parameter:+word}
? Czy ktoś mógłby potwierdzić tę hipotezę?
Odpowiedzi:
To dla kompatybilności z powłoką Bourne'a. Powłoka Bourne'a była starą powłoką, która została po raz pierwszy wydana z Unixem w wersji 7 w 1979 roku i nadal była popularna do połowy lat 90., jak
/bin/sh
w większości komercyjnych Unics.Jest przodkiem najbardziej Bourne podobnych powłok , takich jak
ksh
,bash
lubzsh
.Miał kilka niezręcznych funkcji, z których wiele zostało naprawionych,
ksh
a inne powłoki i nową standardową specyfikacjęsh
, z których jedna to:Z powłoką Bourne'a (przynajmniej te warianty, w których nie został naprawiony):
"$@"
rozwija się do jednego pustego argumentu, jeśli lista parametrów pozycyjnych jest pusta ($# == 0
) zamiast żadnego argumentu.${var+something}
rozwija się do „czegoś”, chyba że$var
jest rozbrojone. Jest to wyraźnie udokumentowane we wszystkich powłokach, ale trudno je znaleźć wbash
dokumentacji, ponieważ należy zwrócić uwagę na to zdanie:${1+"$@"}
Rozwija się więc"$@"
tylko do funkcji$1
set ($# > 0
), która działa wokół tego ograniczenia powłoki Bourne'a.Zauważ, że powłoka Bourne'a jest jedyną powłoką z tym problemem. Nowoczesne
sh
s (które sąsh
zgodne ze specyfikacją POSIXsh
(której nie ma powłoka Bourne'a)) nie mają tego problemu. Potrzebujesz tego tylko wtedy, gdy potrzebujesz kodu do pracy na bardzo starych systemach, w których/bin/sh
może być powłoką Bourne'a zamiast standardowej powłoki (zauważ, że POSIX nie określa lokalizacji standardush
, więc na przykład w Solarisie przed Solaris 11,/bin/sh
nadal był powłoką Bourne'a (chociaż nie miał tego konkretnego problemu), podczas gdy normalny / standardowysh
znajdował się w innej lokalizacji (/usr/xpg4/bin/sh
)).Istnieje jednak problem na tej
perlrun
stronie perldoc, który$0
nie jest cytowany.Aby uzyskać więcej informacji, zobacz http://www.in-ulm.de/~mascheck/various/bourne_args/ .
źródło
Istnieje różnica między:
i
W jednym przekazujesz jeden argument, który jest pustym ciągiem. W drugim przypadku przekazano zero argumentów.
Dla obu, „$ @” będzie zbliżać się do tej samej rzeczy:
""
. Ale użycie${1:+"$@"}
byłoby""
pierwsze, a argumenty nie były przekazywane za drugim, co było celem.Staje się to ważne, jeśli wykonujesz coś w skrypcie poniżej, zwanym sshwrapper, który wywołujesz za pomocą opcjonalnego polecenia lub bez argumentów w celu uzyskania interaktywnej powłoki.
Spowoduje to próbę uruchomienia „” na zdalnym hoście (który właśnie zwraca), nie byłby to interaktywna powłoka.
Uruchamia interaktywną powłokę na zdalnym hoście, ponieważ exec poprawnie interpretuje zmienną jako nic, a nie pusty ciąg.
Przeczytaj o użyciu „$ {parametr: + słowo}” („Użyj wartości alternatywnej”) i podobnych ciągów zmiennych zmiennych na stronach podręcznika bash.
źródło
sh
implementacji zgodnej z POSIX (patrz inna odpowiedź).${1:+"$@"}
rozwinąłby się do braku argumentu, gdyby$1
był pusty. Chcesz${1+"$@"}
. Zasadniczo masz odwrócone.Podsumowałem odpowiedź Stéphane'a Chazelasa:
więc jeśli użyjesz drugiego z parametrem „”, oznacza to, że $ 1 jest zerowy, ale nie sprawdza, czy jest pusty, czy nie, po prostu widzi, że został już ustawiony, ale jest pusty czy nie, więc rozwinie się $ @ , ale używasz $ {1: + "$ @"} 'z „”, nie będzie się już rozwijał
$@
.źródło