Zwykle $@
reprezentujemy wszystkie argumenty oprócz 0. Nie wiem jednak, jaka $@
jest struktura danych .
Dlaczego zachowuje się inaczej w $*
przypadku podwójnego cytatu, czy ktoś mógłby mi wyjaśnić na poziomie tłumacza?
Może być iterowany w pętli for, więc wygląda na tablicę. Jednak można go również w całości powtórzyć za pomocą prostej echo $@
, jeśli jest to tablica, zostanie pokazany tylko pierwszy element. Z powodu ograniczenia powłoki nie mogę napisać więcej kodu eksperymentu, aby go wykonać.
Różnica między tym postem : Ten post pokazuje, jak $@
się inaczej zachowuje $*
. Ale zastanawiam się nad typem danych $@
. Shell jako język interpretacyjny, podobnie jak Python, powinien reprezentować dane zgodnie z szeregiem podstawowych typów. Innymi słowy, chcę wiedzieć, jak $ @ przechowywane w pamięci komputera.
Czy jest to ciąg, ciąg wielu linii czy tablica?
Jeśli jest to unikalny typ danych, czy można zdefiniować zmienną niestandardową jako instancję tego typu?
printf '%s\n' "$@"
iprintf '%s\n' "$*"
.echo
Narzędzie po prostu wyprowadza swoje argumenty, nie ważne czy są one jednego lub wielu. Obie są tablicami (ciągów), ale zachowują się inaczej, gdy są podwójnie cytowane. Gdyby którykolwiek był łańcuchem wieloliniowym, nie byliby w stanie przechowywać łańcuchów wieloliniowych (co mogą). Nie jest jasne, jaki problem próbujesz rozwiązać.@var
zmienna jest w Perlu, pod względem podstawowej pamięci. Z punktu widzenia zwykłego programu Perla nie ma to tak naprawdę znaczenia, poza tym, że jest on dostępny jako tablica / lista (oraz fakt, że istnieją konteksty, w których oczekiwana jest lista).Odpowiedzi:
Zaczęło się od włamania do powłoki Bourne'a. W powłoce Bourne'a dzielono słowa IFS (po tokenizacji) na wszystkie słowa w kontekście listy (argumenty linii poleceń lub słowa na
for
pętli). Gdybyś miał:Że druga linia będzie tokenised w 3 słowach,
$var
będzie rozszerzona i podzielonego + glob byłyby wykonywane na wszystkich trzech słowach, tak by skończyć uruchomionyed
zt
,f
,le.txt
,f
,le2.txt
jako argumenty.Cytowanie części tego zapobiegłoby podziałowi + globowi. Powłoka Bourne'a początkowo pamiętała, które znaki były cytowane, ustawiając na nich 8. bit (to zmieniło się później, gdy Unix stał się 8-bitowy czysty, ale powłoka nadal robiła coś podobnego, aby zapamiętać, który bajt był cytowany).
Zarówno
$*
i$@
były konkatenacją pozycyjnych z przestrzeni między nimi. Ale było specjalne przetwarzanie,$@
kiedy wewnątrz podwójnych cudzysłowów. Jeśli$1
zawartefoo bar
i$2
zawartebaz
,"$@"
rozwija się do:(z
^
powyższymi literami „s” wskazującymi, który ze znaków ma ustawiony 8. bit). Gdzie cytowano pierwszą spację (ustawiono 8 bit), ale nie drugą (ta dodawana pomiędzy słowami).I to rozdzielenie IFS dba o rozdzielenie argumentów (zakładając, że znak spacji jest
$IFS
taki, jaki jest domyślnie). Jest to podobne do tego, jak$*
zostało rozszerzone w swoim poprzedniku, powłoce Mashey (sama oparta na powłoce Thomsona, podczas gdy powłoka Bourne'a została napisana od zera).To wyjaśnia, dlaczego w Bourne shell początkowo
"$@"
rozwinie się do pustej struny zamiast w ogóle nic, gdy lista parametrów pozycyjnych była pusta (trzeba było obejść się${1+"$@"}
), dlaczego nie trzymać puste parametry pozycyjne i dlaczego"$@"
didn działa, gdy$IFS
nie zawiera znaku spacji.Chodziło o to, aby móc przekazać listę argumentów dosłownie do innego polecenia, ale to nie działało poprawnie dla pustej listy, pustych elementów lub gdy
$IFS
nie zawierało spacji (pierwsze dwa problemy zostały ostatecznie naprawione w późniejszych wersjach ).Powłoka Korna (na której oparta jest specyfikacja POSIX) zmieniła to zachowanie na kilka sposobów:
edit
lubfile.txt
w powyższym przykładzie)$*
i$@
są łączone z pierwszym znakiem$IFS
lub spacją, gdy$IFS
jest pusty, z wyjątkiem tego, że dla cudzysłowu"$@"
, ten łącznik nie jest cytowany jak w powłoce Bourne'a, a dla cudzysłowu,"$*"
gdyIFS
jest pusty, parametry pozycyjne są dodawane bez separatora.${array[@]}
${array[*]}
przypomina Bourne$*
i$@
lecz wychodząc z índice 0 zamiast 1, oraz fragmentarycznych (bardziej asocjacyjnych), które to środki$@
nie mogę być traktowane jako tablica ksh (porównaj zcsh
/rc
/zsh
/fish
/yash
gdzie$argv
/$*
jest normalne tablice)."$@"
kiedy$#
0 jest teraz interpretowane jako nic zamiast pustego ciągu,"$@"
działa, gdy$IFS
nie zawiera spacji, z wyjątkiem gdyIFS
jest pusty.$*
Bez cudzysłowu bez symboli zastępczych rozwija się do jednego argumentu (gdzie parametry pozycyjne są łączone ze spacją), gdy$IFS
jest pusty.ksh93 naprawił pozostałe kilka problemów powyżej. W ksh93,
$*
i$@
rozszerza się do listy parametrów pozycyjnych, oddzielone niezależnie od wartości$IFS
, a następnie dalej podzielone + globbed + klamra rozszerzone w kontekście lista,$*
połączone z pierwszym bajcie (nie znaków) z$IFS
,"$@"
w kontekście lista rozwija się na liście parametrów pozycyjnych, niezależnie od wartości$IFS
. W kontekście innym niż lista, jak wvar=$@
,$@
jest łączony ze spacją niezależnie od wartości$IFS
.bash
Tablice są zaprojektowane po ksh. Różnice są następujące:$IFS
zamiast zamiast bajtu$*
gdy nie jest cytowany w kontekście innym niż lista, gdy$IFS
jest pusty.Podczas gdy specyfikacja POSIX była dość niejasna, teraz mniej więcej określa zachowanie bash.
Różni się od zwykłych tablic w tym
ksh
lubbash
w tym:"${@:0}"
gdy zawiera$0
(nie parametr pozycyjny, a w funkcjach daje nazwę funkcji lub nie zależy od powłoki i sposobu jej zdefiniowania)).shift
może być użyte.W
zsh
lubyash
gdzie tablice są normalnymi tablicami (nie rzadkimi, indeksy zaczynają się od jedności jak we wszystkich innych powłokach, ale ksh / bash),$*
są traktowane jak normalna tablica.zsh
ma$argv
jako alias (dla kompatybilności zcsh
).$*
jest taki sam jak$argv
lub${argv[*]}
(argumenty połączone z pierwszym znakiem,$IFS
ale nadal rozdzielone w kontekstach listy)."$@"
polubić"${argv[@]}"
lub"${*[@]}"}
poddać specjalnej obróbce w stylu Korna.źródło
Jest to specjalny parametr, który rozszerza się na wartości parametrów pozycyjnych ... Ale to nie jest w porządku z terminologią.
Możemy wyświetlać parametry pozycyjne jako części
$@
, więc ma on wiele odrębnych elementów ($1
,$2
...), do których można uzyskać dostęp niezależnie i które są nazywane kolejnymi liczbami naturalnymi. To sprawia, że jest to coś, co zwykle nazywa się tablicą.Składnia jest jednak nieco dziwna, a nawet ograniczona. Nie ma możliwości modyfikacji pojedynczego elementu tablicy indywidualnie. Zamiast tego wszystko musi być ustalone na raz. (Możesz użyć,
set -- "$@" foo
aby dodać wartość lubset -- "${@:1:2}" foo "${@:3}"
dodać wartość na środku. Ale w obu przypadkach musisz zapisać całą wynikową listę).Ponieważ są zdefiniowane, aby zachowywać się inaczej.
Jeśli masz na myśli fakt, że
a=(foo bar asdf); echo $a
właśnie wypisze dane wyjściowefoo
, to jest to głównie dziwactwo składni powłoki oraz fakt, że nazwane tablice w stylu ksh powstały później niż parametry pozycyjne i$@
. Zwykły$a
jest taki sam, ponieważ${a[0]}
ma kompatybilne wstecz znaczenie pojedynczej wartości skalarnej, niezależnie od tego, czya
jest tablicą czy zwykłą zmienną skalarną.@
Znak odnoszący się do całej listy został użyty za wymienionych w tablicach, że"${a[@]}"
jest sposób, aby uzyskać całą listę. W porównaniu do nazwanych tablic,$@
niepotrzebne nawiasy klamrowe i nawiasy oraz nazwa są po prostu pomijane.To zależy od implementacji, musisz poszukać kodu źródłowego dowolnej powłoki, na której ci zależy.
Głównie tablica. Chociaż różnią się od nazwanych tablic w stylu ksh, ponieważ mogą mieć dowolne nieujemne liczby całkowite jako indeksy, a nie tylko kolejne, jak z
$@
. (Oznacza to, że tablica może być nazwany rzadki i mieć np indeksów1
,3
a4
ze0
i2
brakuje. To nie jest to możliwe z parametrów pozycyjnych).Nie jest to pojedynczy ciąg, ponieważ można go rozwinąć do odrębnych elementów, a wywoływanie linii elementów również nie jest właściwe, ponieważ dowolna zmienna regularna lub jeden z parametrów pozycyjnych (elementów
$@
) może również zawierać znaki nowej linii.Nie. Ale tablice nazwane i tak są prawdopodobnie bardziej przydatne.
źródło
$@
nie jest strukturą danych, jest jedną z niewielu funkcji / operatorów do rozszerzania struktury danych parametrów pozycyjnych.