Dlaczego $ {$ #} zwraca ten sam wynik co $$ w powłoce?

18

Starając się uzyskać ostatniego pozycyjny zestaw parametrów w /bin/dash, próbowałem echo ${$#}. Nieoczekiwanie nie spowodowało to błędu, ale PID, który jest taki sam jak $$zmienna zawartość. Pytanie, dlaczego ta składnia działała? Jaką zasadę składni zastosowała tutaj powłoka?

Zasadniczo to, co zrobiłem

$ set 1 2 3 4 5
$ echo ${$#}
13819
$ echo $$
13819

Najwyraźniej %postać jest również ignorowana w takiej konstrukcji

$ echo ${$%}
13819

Ale *i @skutkują złym błędem podstawienia:

$ echo ${$*}
sh: 10: Bad substitution
$ echo ${$@}
sh: 11: Bad substitution
Sergiy Kolodyazhnyy
źródło
3
Czego oczekujesz ${$*}i ${$@}produkujesz?
Kusalananda
2
@Kusalananda Brak oczekiwań. Starałem inne znaki obok #i %i co wynika z tych zachowań.
Sergiy Kolodyazhnyy
1
Aby faktycznie wykonać pośrednie działanie w Dash, użyj evalnp dash -c 'set 1 2 3 4 5; eval "echo \$$#"'. Źródło: Ubuntu Wiki
wjandrea
1
@wjandrea Tak, już o tym wiem. W rzeczywistości jest już pytanie na ten temat: stackoverflow.com/questions/1853946/ ... Próbowałem znaleźć metodę samemu, nie czytając najpierw pytania (i wiedziałem, że mogę for i; do true; donedostać ostatni element $i), ale szukałem czegoś bardziej eleganckiego. evaloczywiście mogą mieć potencjalne problemy, choć w jakim stopniu - to inny temat. Ale tak, jest to opcja
Sergiy Kolodyazhnyy

Odpowiedzi:

35

Jest to $$ po usunięciu pustego prefiksu :

${parameter#[word]}

Usuń najmniejszy wzór prefiksu . Słowo zostanie rozszerzona do produkcji wzoru. Rozszerzanie parametru powinno następnie skutkować parametrem , przy czym najmniejsza część prefiksu jest dopasowana do wzorca usuniętego. Jeśli występuje, słowo nie może zaczynać się od cudzysłowu #.

To samo dotyczy %(sufiks). @i *nie są modyfikatorami rozszerzenia parametrów, więc są błędami. Byłoby to zdarzyć $?, $-lub hipotetyczna $=, jak również. ${$+}jest pustym rozszerzeniem.

Michael Homer
źródło
Powinienem był natychmiast rozpoznać podstawienie parametru. Dobry chwyt
Sergiy Kolodyazhnyy