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
--debugger
Option). Wenn nach dem Aufruf festgelegt, ist das für Debugger vorgesehene Verhalten aktiviert:
- Die
-F
Option zumdeclare
Builtin (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 -f
scheint 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 -P
aktiviert 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 -h
Flag unterdrückt das Drucken der Dateinamen, bei denen eine Übereinstimmung gefunden wurde. Dies grep
gilt standardmäßig, wenn Sie aufgefordert werden, mehrere Dateien zu durchsuchen. Das -o
bedeutet "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- -o
Flag 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/$c
und ")\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 ~/.bashrc
und Sie können dann ausführen (ich verwende fooBar
als Beispiel einen Funktionsnamen):
grep_function fooBar
Zum Beispiel, wenn ich diese Zeile in meinem habe ~/.bashrc
:
. ~/a
Und die Datei ~/a
ist:
$ cat ~/a
fooBar(){
echo foo
}
Ich sollte es finden mit:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"
die Zeichenfolge foo
an 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_aliases
und aufbewahren ~/.bash_functions
, was das Auffinden dieser Dateien erheblich erleichtert. Sie können die Suche .bashrc
nach source
Befehlen 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 .bashrc
mit einem einzigen grep
Aufruf durchsuchen , z. B. nach der Funktion foo
für mein Setup:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}