Antworten:
Aktivieren Sie das Debuggen. Aus dem Bash-Handbuch :
extdebug
Wenn dies beim Aufruf der Shell oder in einer Shell-Startdatei festgelegt wurde, führen Sie das Debugger-Profil vor dem Start der Shell aus (identisch mit der
--debuggerOption). Wenn nach dem Aufruf festgelegt, ist das für Debugger vorgesehene Verhalten aktiviert:
- Die
-FOption zumdeclareBuiltin (siehe Bash-Builtins ) zeigt den Namen der Quelldatei und die Zeilennummer an, die den Funktionsnamen entsprechen, die als Argument angegeben werden.
Beispiel:
$ bash --debugger
$ declare -Ff quote
quote 143 /usr/share/bash-completion/bash_completion
Und in der Tat:
$ 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 "$@"; ). Mit den Parens auf dem Funktionskörper wird es in einer Subshell ausgeführt, und die Änderung von shopts hat keine Auswirkungen auf den Aufrufer. Und das -fscheint nicht nötig zu sein.
Dies ist tatsächlich komplizierter als es zunächst erscheint. Welche Dateien von Ihrer Shell gelesen werden, hängt davon ab, welchen Shell-Typ Sie gerade ausführen. Ob es interaktiv ist oder nicht, ob es sich um eine Login- oder eine Nicht-Login-Shell handelt und welche Kombination der oben genannten. So durchsuchen Sie alle Standarddateien, die von den verschiedenen Shells gelesen werden können $functionName:
grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
~/.bash_aliases /etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
Wenn dies nicht funktioniert, rufen Sie möglicherweise eine nicht standardmäßige Datei mit .oder ihrem Alias auf source. Um solche Fälle zu finden, führen Sie Folgendes aus:
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
Das bedarf wahrscheinlich einer Erklärung. Das -Paktiviert Perl-kompatible reguläre Ausdrücke (PCRE), mit denen wir eine ausgefeiltere Regex-Syntax verwenden können. Speziell:
(^|\s): Entspricht entweder dem Anfang einer Zeile ( ^) oder dem Leerzeichen ( \s).(\.|source)\s+: Entspricht entweder einem Literalzeichen .( \.) oder dem Wort source, jedoch nur, wenn auf dieses ein oder mehrere Leerzeichen folgen.Folgendes gibt mir auf meinem 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
Wie Sie jedoch sehen können, wird die gesamte übereinstimmende Zeile gedruckt. Was uns wirklich interessiert, ist die Liste der aufgerufenen Dateinamen, nicht die Zeile, die sie aufruft. Sie können diese mit diesem, komplizierteren, regulären Ausdruck erhalten:
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
Das -hFlag unterdrückt das Drucken der Dateinamen, bei denen eine Übereinstimmung gefunden wurde. Dies grepgilt standardmäßig, wenn Sie aufgefordert werden, mehrere Dateien zu durchsuchen. Das -obedeutet "nur den passenden Teil der Zeile drucken". Die zusätzlichen Dinge, die zum regulären Ausdruck hinzugefügt werden, sind:
\K: Ignoriere alles, was bis zu diesem Punkt gepasst hat. Dies ist ein PCRE-Trick, mit dem Sie einen komplexen regulären Ausdruck verwenden können, um Ihre Übereinstimmung zu finden, aber diesen übereinstimmenden Teil nicht einschließen, wenn Sie das grep- -oFlag verwenden.Auf meinem System wird der obige Befehl zurückgegeben:
$ 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
Beachten Sie, dass ich zufällig .gefolgt von einem Leerzeichen benutze, das nicht für das Sourcing verwendet wird, aber das liegt daran, dass ich einen Alias habe, der eine andere Sprache aufruft, nicht Bash. Das ist es, was die seltsame $a*100/$cund ")\n"'in der Ausgabe oben gibt. Das kann man aber ignorieren.
Zum Schluss erfahren Sie, wie Sie all das zusammenfassen und in allen Standarddateien und allen Dateien, die Ihre Standarddateien beziehen, nach einem Funktionsnamen suchen :
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
}
Fügen Sie diese Zeilen zu Ihrer hinzu ~/.bashrcund Sie können dann ausführen (ich verwende fooBarals Beispiel einen Funktionsnamen):
grep_function fooBar
Zum Beispiel, wenn ich diese Zeile in meinem habe ~/.bashrc:
. ~/a
Und die Datei ~/aist:
$ cat ~/a
fooBar(){
echo foo
}
Ich sollte es finden mit:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"die Zeichenfolge fooan das erste Element des Arrays anzuhängen?
Das üblichebash Lesen von Punktdateien pro Benutzer ist ~/.bashrc. Es kann jedoch durchaus sein, dass andere Dateien als Quelle vorliegen. Ich möchte beispielsweise Aliase und Funktionen in separaten Dateien namens ~/.bash_aliasesund aufbewahren ~/.bash_functions, was das Auffinden dieser Dateien erheblich erleichtert. Sie können die Suche .bashrcnach sourceBefehlen mit:
grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
Sobald Sie die Liste der vom Benutzer erstellten Dateien haben, können Sie sie und den Benutzer .bashrcmit einem einzigen grepAufruf durchsuchen , z. B. nach der Funktion foofür mein Setup:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}