Jak mogę znaleźć, gdzie zdefiniowano określoną funkcję bash?
28
Istnieje wiele funkcji, które mogą być używane w powłoce Bash. Ich definicje mogą być wymienione według set, ale jak znaleźć w jakich plikach zdefiniowane są określone funkcje zdefiniowane przez użytkownika?
Jeśli ustawione przy wywołaniu powłoki lub w pliku startowym powłoki, należy ustawić profil debuggera przed uruchomieniem powłoki, identycznie jak w
--debuggeropcji. Jeśli ustawione po wywołaniu, zachowanie przeznaczone do użycia przez debuggery jest włączone:
-FOpcja do declarewbudowanego polecenia (zobacz Bash builtins ) wyświetla nazwę pliku źródłowego i linia numer odpowiadający każdej nazwy funkcji dostarczanych jako argument.
To świetne i proste rozwiązanie. Jak dla przykładu, nie jest nawet konieczne, aby rozpocząć nową powłokę: shopt -s extdebug; declare -Ff quote; shopt -u extdebug.
jarno
2
@jarno ah, cóż, w przeciwieństwie do mojego imienia, używam zsh. Dlatego zacząłem nową powłokę. : D
bashity mcbashface
Czy istnieje podobna metoda znajdowania lokalizacji deklaracji aliasów ?
FedonKadifeli
@fedon moje zawiłe i skomplikowane podejście poniżej powinno zadziałać.
terdon
1
Można zrobić to funkcja tak: find_function()( shopt -s extdebug; declare -F "$@"; ). Dzięki parens na ciele funkcji, jest wykonywany w podpowłoce, a zmiana na shopts nie wpływa na wywołującego. I -fnie wydaje się to potrzebne.
wjandrea
15
Jest to w rzeczywistości bardziej skomplikowane, niż się wydaje. To, które pliki są odczytywane przez powłokę, zależy od typu aktualnie uruchomionej powłoki . Niezależnie od tego, czy jest to interaktywna, czy nie, czy jest to powłoka do logowania, czy bez logowania, oraz jaka kombinacja powyższych. Aby przeszukać wszystkie domyślne pliki, które mogą być odczytane przez różne powłoki, możesz to zrobić (zmień $functionNamena rzeczywistą nazwę szukanej funkcji):
Jak widać, spowoduje to wydrukowanie całej dopasowanej linii. Najbardziej interesuje nas lista nazw plików, a nie linia, która je wywołuje. Możesz uzyskać te za pomocą tego, bardziej skomplikowanego wyrażenia regularnego:
-hFlaga hamuje drukowanie nazwy pliku, w którym mecz został znaleziony, który greprobi domyślnie kiedy powiedział do przeszukiwania wielu plików. Te -ośrodki „tylko wydrukować część dopasowanie linii”. Dodatkowe rzeczy dodane do wyrażenia regularnego to:
\K: zignoruj wszystko dopasowane do tego momentu. Jest to sztuczka PCRE, która pozwala użyć złożonego wyrażenia regularnego, aby znaleźć dopasowanie, ale nie obejmuje tej dopasowanej części, gdy używasz -oflagi grep .
Zauważ, że zdarza mi się używać znaku .spacji, który nie jest używany do pozyskiwania, ale to dlatego, że mam alias, który woła inny język, a nie bash. To daje dziwne $a*100/$ci ")\n"'powyższe wyniki. Ale można to zignorować.
Na koniec, oto jak to wszystko połączyć i wyszukać nazwę funkcji we wszystkich domyślnych plikach i we wszystkich plikach, które pozyskują Twoje domyślne pliki:
grep_function(){
target="$@"
files=(~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login
~/.bash_aliases /etc/bash.bashrc /etc/profile
/etc/profile.d/*/etc/environment)while IFS= read -r file;do
files+=("$file")done<<(grep -hPo '(^|\s)(\.|source)\s+\K\S+'"${files[@]}"2>/dev/null)for file in"${files[@]}";do## The tilde of ~/ can break this
file=$(sed 's|~/|'"$HOME"'/|g'<<<"$file")if[[-e $file ]];then
grep -H "$target"--"$file"fidone}
Dodaj te wiersze do swojego ~/.bashrci możesz następnie uruchomić (używam fooBarjako przykładowej nazwy funkcji):
Twoje rozwiązanie jest świetnym przykładem skryptu edukacyjnego, ale uważam, że rozwiązanie bashity mcbashface jest prostsze.
jarno
@jarno i jest o wiele, wiele prostsze! :)
terdon
Obsługa tablic+=
D. Ben Knoble
@ D.BenKnoble robią? Masz na myśli inne niż array+="foo"dołączenie ciągu foodo pierwszego elementu tablicy?
terdon
1
@ D.BenKnoble dzięki! Nie wiedziałem, że tablice bash obsługują ten zapis!
terdon
2
Zwykle per-user dotfile bashczyta to ~/.bashrc. Może jednak bardzo dobrze pozyskiwać inne pliki, na przykład lubię przechowywać aliasy i funkcje w osobnych plikach o nazwie ~/.bash_aliasesi ~/.bash_functions, co znacznie ułatwia ich znalezienie. Możesz wyszukiwać polecenia .bashrcza sourcepomocą:
Gdy masz już listę plików utworzonych przez użytkownika, możesz je wyszukać i użytkownika .bashrcza pomocą jednego greppołączenia, np. W celu uzyskania funkcji foodla mojej konfiguracji:
Odpowiedzi:
Włącz debugowanie. Z podręcznika Bash :
Przykład:
I rzeczywiście:
źródło
shopt -s extdebug; declare -Ff quote; shopt -u extdebug
.find_function()( shopt -s extdebug; declare -F "$@"; )
. Dzięki parens na ciele funkcji, jest wykonywany w podpowłoce, a zmiana na shopts nie wpływa na wywołującego. I-f
nie wydaje się to potrzebne.Jest to w rzeczywistości bardziej skomplikowane, niż się wydaje. To, które pliki są odczytywane przez powłokę, zależy od typu aktualnie uruchomionej powłoki . Niezależnie od tego, czy jest to interaktywna, czy nie, czy jest to powłoka do logowania, czy bez logowania, oraz jaka kombinacja powyższych. Aby przeszukać wszystkie domyślne pliki, które mogą być odczytane przez różne powłoki, możesz to zrobić (zmień
$functionName
na rzeczywistą nazwę szukanej funkcji):Jeśli to nie zadziała, być może dzwonisz do pliku innego niż domyślny przy użyciu
.
lub jego aliasusource
. Aby znaleźć takie przypadki, uruchom:To chyba wymaga wyjaśnienia.
-P
Umożliwia pcre (PCRE), które pozwalają nam używać trochę bardziej wyszukane składni regex. Konkretnie:(^|\s)
: dopasuj początek linii (^
) lub białego znaku (\s
).(\.|source)\s+
: dopasuj literał.
(\.
) lub słowosource
, ale tylko wtedy, gdy po nich następuje jeden lub więcej białych znaków.Oto, co daje mi mój system:
Jak widać, spowoduje to wydrukowanie całej dopasowanej linii. Najbardziej interesuje nas lista nazw plików, a nie linia, która je wywołuje. Możesz uzyskać te za pomocą tego, bardziej skomplikowanego wyrażenia regularnego:
-h
Flaga hamuje drukowanie nazwy pliku, w którym mecz został znaleziony, którygrep
robi domyślnie kiedy powiedział do przeszukiwania wielu plików. Te-o
środki „tylko wydrukować część dopasowanie linii”. Dodatkowe rzeczy dodane do wyrażenia regularnego to:\K
: zignoruj wszystko dopasowane do tego momentu. Jest to sztuczka PCRE, która pozwala użyć złożonego wyrażenia regularnego, aby znaleźć dopasowanie, ale nie obejmuje tej dopasowanej części, gdy używasz-o
flagi grep .W moim systemie powyższe polecenie zwróci:
Zauważ, że zdarza mi się używać znaku
.
spacji, który nie jest używany do pozyskiwania, ale to dlatego, że mam alias, który woła inny język, a nie bash. To daje dziwne$a*100/$c
i")\n"'
powyższe wyniki. Ale można to zignorować.Na koniec, oto jak to wszystko połączyć i wyszukać nazwę funkcji we wszystkich domyślnych plikach i we wszystkich plikach, które pozyskują Twoje domyślne pliki:
Dodaj te wiersze do swojego
~/.bashrc
i możesz następnie uruchomić (używamfooBar
jako przykładowej nazwy funkcji):Na przykład, jeśli mam tę linię w moim
~/.bashrc
:Plik
~/a
to:Powinienem to znaleźć z:
źródło
+=
array+="foo"
dołączenie ciągufoo
do pierwszego elementu tablicy?Zwykle per-user dotfile
bash
czyta to~/.bashrc
. Może jednak bardzo dobrze pozyskiwać inne pliki, na przykład lubię przechowywać aliasy i funkcje w osobnych plikach o nazwie~/.bash_aliases
i~/.bash_functions
, co znacznie ułatwia ich znalezienie. Możesz wyszukiwać polecenia.bashrc
zasource
pomocą:Gdy masz już listę plików utworzonych przez użytkownika, możesz je wyszukać i użytkownika
.bashrc
za pomocą jednegogrep
połączenia, np. W celu uzyskania funkcjifoo
dla mojej konfiguracji:źródło