Jawaban:
Aktifkan debugging. Dari manual Bash :
extdebug
Jika diset pada permintaan shell, atau dalam file startup shell, atur untuk menjalankan profil debugger sebelum shell dimulai, identik dengan
--debugger
opsi. Jika disetel setelah pemanggilan, perilaku yang dimaksudkan untuk digunakan oleh para debugger diaktifkan:
- The
-F
pilihan untukdeclare
builtin (lihat Bash builtin ) menampilkan sumber nama file dan nomor baris yang sesuai untuk setiap nama fungsi yang disediakan sebagai argumen.
Contoh:
$ bash --debugger
$ declare -Ff quote
quote 143 /usr/share/bash-completion/bash_completion
Dan memang:
$ 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 "$@"; )
. Dengan parens pada badan fungsi, dieksekusi dalam subkulit dan perubahan ke shopts tidak memengaruhi pemanggil. Dan -f
sepertinya tidak dibutuhkan.
Ini sebenarnya lebih rumit daripada yang muncul pada awalnya. File mana yang dibaca oleh shell Anda tergantung pada jenis shell yang sedang Anda jalankan. Apakah itu interaktif atau tidak, apakah itu login atau shell non-login dan apa kombinasi di atas. Untuk mencari semua file default yang dapat dibaca oleh shell yang berbeda, Anda dapat melakukannya (mengubah $functionName
ke nama sebenarnya dari fungsi yang Anda cari):
grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
~/.bash_aliases /etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
Jika itu tidak berhasil, Anda mungkin memanggil file non-default menggunakan .
atau aliasnya source
. Untuk menemukan kasus seperti itu, jalankan:
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
Itu mungkin perlu penjelasan. Yang -P
memungkinkan Perl Compatible Regular Expressions (PCRE) yang memungkinkan kami menggunakan sintaks regex yang lebih menarik. Secara khusus:
(^|\s)
: cocok dengan awal suatu baris ( ^
) atau spasi putih ( \s
).(\.|source)\s+
: cocok dengan .
karakter literal ( \.
) atau kata source
, tetapi hanya jika mereka diikuti oleh satu atau lebih karakter spasi putih.Inilah yang memberi saya pada sistem saya:
$ 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
Seperti yang Anda lihat, bagaimanapun, ini akan mencetak seluruh baris yang cocok. Yang benar-benar kami minati adalah daftar nama file yang dipanggil, bukan baris yang memanggil mereka. Anda bisa mendapatkannya dengan ini, lebih rumit, regex:
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
The -h
bendera menekan pencetakan nama file di mana pertandingan ditemukan, yang grep
tidak secara default ketika diberitahu untuk mencari melalui beberapa file. The -o
berarti "hanya mencetak bagian pencocokan dari garis". Hal-hal tambahan yang ditambahkan ke regex adalah:
\K
: abaikan apa pun yang cocok dengan titik ini. Ini adalah trik PCRE yang memungkinkan Anda menggunakan regex kompleks untuk menemukan pasangan Anda, tetapi tidak menyertakan bagian yang cocok saat menggunakan -o
bendera grep .Di sistem saya, perintah di atas akan kembali:
$ 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
Perhatikan bahwa saya kebetulan menggunakan .
diikuti oleh ruang yang tidak digunakan untuk sumber tetapi itu karena saya memiliki alias yang memanggil bahasa lain, bukan bash. Itulah yang memberi keanehan $a*100/$c
dan ")\n"'
pada output di atas. Tapi itu bisa diabaikan.
Terakhir, inilah cara menyatukan semua itu dan mencari nama fungsi di semua file default dan semua file yang menjadi sumber file default Anda:
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
}
Tambahkan baris-baris itu ke Anda ~/.bashrc
dan Anda kemudian dapat menjalankan (saya menggunakan fooBar
sebagai contoh nama fungsi):
grep_function fooBar
Misalnya, jika saya memiliki baris ini di ~/.bashrc
:
. ~/a
Dan file tersebut ~/a
adalah:
$ cat ~/a
fooBar(){
echo foo
}
Saya harus menemukannya dengan:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"
menambahkan string foo
ke elemen pertama array?
The biasa per-user dotfile bash
membaca adalah ~/.bashrc
. Namun, mungkin sumber file lain sangat baik, saya misalnya ingin menjaga alias dan fungsi dalam file terpisah yang disebut ~/.bash_aliases
dan ~/.bash_functions
, yang membuatnya lebih mudah menemukannya. Anda dapat mencari .bashrc
untuk source
perintah dengan:
grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
Setelah Anda memiliki daftar file yang dibuat pengguna, Anda dapat mencarinya dan pengguna .bashrc
dengan satu grep
panggilan, misalnya untuk fungsi foo
pengaturan saya:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}