Odpowiedzi:
Włącz debugowanie. Z podręcznika Bash :
extdebug
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
--debugger
opcji. Jeśli ustawione po wywołaniu, zachowanie przeznaczone do użycia przez debuggery jest włączone:
-F
Opcja dodeclare
wbudowanego polecenia (zobacz Bash builtins ) wyświetla nazwę pliku źródłowego i linia numer odpowiadający każdej nazwy funkcji dostarczanych jako argument.
Przykład:
$ bash --debugger
$ declare -Ff quote
quote 143 /usr/share/bash-completion/bash_completion
I rzeczywiście:
$ nl -ba /usr/share/bash-completion/bash_completion | sed -n 143,150p
143 quote()
144 {
145 local quoted=${1//\'/\'\\\'\'}
146 printf "'%s'" "$quoted"
147 }
148
149 # @see _quote_readline_by_ref()
150 quote_readline()
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):
grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
~/.bash_aliases /etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
Jeśli to nie zadziała, być może dzwonisz do pliku innego niż domyślny przy użyciu .
lub jego aliasu source
. Aby znaleźć takie przypadki, uruchom:
grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
/etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
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łowo source
, ale tylko wtedy, gdy po nich następuje jeden lub więcej białych znaków.Oto, co daje mi mój system:
$ grep -P '(^|\s)(\.|source)\s+' ~/.bashrc ~/.profile ~/.bash_profile \
> ~/.bash.login ~/.bash_aliases /etc/bash.bashrc \
> /etc/profile /etc/profile.d/* /etc/environment 2> /dev/null
/home/terdon/.bashrc: . /etc/bashrc
/home/terdon/.bashrc: . /etc/bash_completion
/home/terdon/.bashrc:. $HOME/scripts/git-prompt.sh
/home/terdon/.bashrc:# echo -n "$n : "; grep "^CA" $n |perl -e 'my ($a,$c)=0; while(<>){$c++;next if /cellular_component_unknown/; next if /biological_process/; $a++} print "$a Classes of $c annotated (" . $a*100/$c . ")\n"'
/etc/bash.bashrc:[ -r /usr/share/bash-completion/bash_completion ] && . /usr/share/bash-completion/bash_completion
/etc/profile: test -r "$profile" && . "$profile"
/etc/profile: . /etc/bash.bashrc
/etc/profile.d/locale.sh: . "$XDG_CONFIG_HOME/locale.conf"
/etc/profile.d/locale.sh: . "$HOME/.config/locale.conf"
/etc/profile.d/locale.sh: . /etc/locale.conf
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
/etc/profile.d/Z97-byobu.sh: . /usr/bin/byobu-launch
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:
grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
~/.bash.login ~/.bash_aliases \
/etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
-h
Flaga hamuje drukowanie nazwy pliku, w którym mecz został znaleziony, który grep
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:
$ grep -hPo '(^|\s)(\.|source)\s+\K\S+' ~/.bashrc ~/.profile ~/.bash_profile \
> ~/.bash.login ~/.bash_aliases \
> /etc/bash.bashrc /etc/profile \
> /etc/profile.d/* /etc/environment 2> /dev/null
/etc/bashrc
/etc/bash_completion
$HOME/scripts/git-prompt.sh
$a*100/$c
")\n"'
/usr/share/bash-completion/bash_completion
"$profile"
/etc/bash.bashrc
"$XDG_CONFIG_HOME/locale.conf"
"$HOME/.config/locale.conf"
/etc/locale.conf
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
/usr/bin/byobu-launch
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:
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"
fi
done
}
Dodaj te wiersze do swojego ~/.bashrc
i możesz następnie uruchomić (używam fooBar
jako przykładowej nazwy funkcji):
grep_function fooBar
Na przykład, jeśli mam tę linię w moim ~/.bashrc
:
. ~/a
Plik ~/a
to:
$ cat ~/a
fooBar(){
echo foo
}
Powinienem to znaleźć z:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"
dołączenie ciągu foo
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
za source
pomocą:
grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
Gdy masz już listę plików utworzonych przez użytkownika, możesz je wyszukać i użytkownika .bashrc
za pomocą jednego grep
połączenia, np. W celu uzyskania funkcji foo
dla mojej konfiguracji:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}