Jak zmusić słowo Bash do odwoływania się do aliasu, funkcji, pliku itp.?

13

Próbując dodać nieco więcej szczegółów do powiązanego pytania , zdałem sobie sprawę, że nie wiem, jak określić, który z dostępnych typów słów Bash ma zostać wykonany. Według help typepięciu rodzajów słów:

  • Alias
  • słowo kluczowe
  • funkcjonować
  • wbudowany
  • plik

Słowo może mieć kilka typów ( trueto tylko przykład; częściej zastępowanym słowem byłoby cd):

$ type -a true
true is a shell builtin
true is /bin/true

Jak wymusić wykonanie określonego synonimu? Jak dotąd, w kolejności pierwszeństwa:

  • alias: Jest to szczególny przypadek, ponieważ ma pierwszeństwo przed wszystkimi innymi synonimami. Wymuszenie tego byłoby użyteczne tylko wtedy, gdy polecenie nie powiedzie się, jeśli nie zdefiniowano aliasu.

    $ 
  • słowo kluczowe:

    $ 
  • funkcjonować:

    $ 
  • wbudowany:

    $ builtin true
  • plik:

    $ command true
    $ $(which true)
    $ /bin/true

Częściowe rozwiązania :

  • Cytując słowo wyklucza aliasy i słowa kluczowe. To jest,

    $ 'true'

    uruchomi tylko funkcję, wbudowany plik lub plik.

l0b0
źródło

Odpowiedzi:

10

To, o co pytasz, nie ma większego sensu.

Słowo kluczowe oznacza, że ​​jest to słowo, które jest częścią składni powłoki. Są one rozpoznawane przez tokenizację. Przywołanie ich wystarczy, aby powłoka przestała rozpoznawać.

Możliwe jest jednak aliasowanie słowa kluczowego w większości powłok. Tak więc aliasy mają pierwszeństwo przed słowami kluczowymi (w efekcie są wcześnie rozwijane, a po nich jest więcej tokenizacji, w której można mieć więcej aliasów, słów kluczowych) ...

aliasy (z wyjątkiem aliasów zsh zdefiniowanych za pomocą alias -gsą rozwijane tylko w pozycji polecenia), więc zazwyczaj nie w builtin the-alias.

funkcje mają pierwszeństwo przed wbudowanymi, a wbudowane przed zewnętrznymi poleceniami (a następnie $PATHdecydują, którego z nich użyć).

Możesz wymusić wbudowane za pomocą:

builtin the-cmd and its args

(choć należy zauważyć, że nie jest to standardowe polecenie).

Możesz wyłączyć aliasy poprzez ich cytowanie (choć cytowana wersja może być również aliasowana w niektórych powłokach).

Na przykład (tutaj składnia zsh) w:

'while'() echo function while
alias 'while=echo alias while'

Pisanie while truefaktycznie wyszedłoby na jaw alias while truei nie byłoby możliwości użycia whilesłowa kluczowego, ponieważ cytowanie go wyłączyłoby zarówno alias, jak i słowo kluczowe.

Wywołalibyśmy tę whilefunkcję na przykład:

'whi'le whatever

Jeśli whilebyłby wbudowany (ale oczywiście nie byłby w tych powłokach, które mają whilesłowo kluczowe), napisałbyś to:

builtin while whatever

Aby wywołać whilepolecenie, napiszesz:

env while whatever

lub w zsh(gdy nie ma shemulacji):

command while whatever 

(w innych powłokach commandzapobiega tylko funkcjom, nie wbudowanym)

Lub

/full/path/to/while whatever

Oczywiście nic nie powstrzymuje cię przed robieniem jeszcze głupszych rzeczy, takich jak:

alias 'while=while "w"hile; do'
"while"() { while "whi"le; done; }

Które przynajmniej w zsh jest poprawne (ale głupie).

Stéphane Chazelas
źródło
Cytując pomija wyszukiwanie aliasu i command pomija wyszukiwanie funkcji, ale żaden z nich nie określa, który z pozostałych synonimów zostanie użyty. Szukam sposobu, aby określić, aby wykonać tylko określony synonim.
l0b0
@ l0b0 „polecenie” pomija wszystkie aliasy, słowa kluczowe i wbudowane.
Stéphane Chazelas
Co do sensu, builtinjest używany na przykład w RVM do zastąpienia w cdcelu uzyskania miłego efektu.
l0b0
Masz rację; i właśnie zweryfikowałem, że to także tłumi funkcje. +1.
l0b0
0

Niezwykle przydatnym dla mnie idiomem jest to:

FALSE=1; TRUE=0
DEVEL_FLAG=$FALSE
...
in_development() { return $DEVEL_FLAG ; }
cd()
{
 if in_development ; then # -D argument to script toggles development flag
   echo "Would run cd $*"
  else
   builtin cd "$@"
 fi
}

Teraz, jeśli uruchomię skrypt z podaną opcją -D, tryb programowania zostanie aktywowany, a cd (lub dowolne inne zawinięte polecenie) wyświetli informacje o debugowaniu

Jest to szczególnie przydatne w skryptach uruchamiających ssh. Pewnie, że mógłbym przełączyć set -x, ale dla mnie jest to bardziej przydatne i czytelne.

Graham Nicholls
źródło
1
Jak to odpowiada na pytanie?
l0b0