Відповіді:
Увімкніть налагодження. З посібника Bash :
extdebug
Якщо встановлено при виклику оболонки або у файлі запуску оболонки, організуйте виконання профілю налагодження до запуску оболонки, ідентичного
--debugger
параметру. Якщо встановлено після виклику, увімкнено поведінку, призначену для використання налагоджувачами:
-F
Варіант доdeclare
вбудованої команді (див Bash Вбудовані командам ) відображає ім'я вихідного файлу і номер рядка , відповідний кожне ім'я функції , що подається в якості аргументу.
Приклад:
$ bash --debugger
$ declare -Ff quote
quote 143 /usr/share/bash-completion/bash_completion
І справді:
$ 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 "$@"; )
. З паренами на тілі функції воно виконується в підрозділі, і зміна на знімки не впливає на абонента. І -f
це, здається, не потрібно.
Це насправді складніше, ніж спочатку. Які файли читає ваша оболонка, залежить від того, який тип оболонки ви зараз використовуєте. Незалежно від того, інтерактивна вона чи ні, чи це оболонка для входу чи не вхід у систему та яка комбінація перерахованого вище. Для пошуку всіх файлів за замовчуванням, які можна прочитати в різних оболонках, ви можете (змінити $functionName
фактичну назву потрібної функції):
grep "$functionName" ~/.bashrc ~/.profile ~/.bash_profile ~/.bash.login \
~/.bash_aliases /etc/bash.bashrc /etc/profile \
/etc/profile.d/* /etc/environment 2> /dev/null
Якщо це не працює, ви можете викликати файл, який не використовується за замовчуванням, за допомогою .
або його псевдоніму source
. Щоб знайти такі випадки, запустіть:
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
Це, мабуть, потребує деяких пояснень. -P
Дозволяє Perl Compatible Regular Expressions (PCRE) , які дозволяють нам використовувати деякі любитель синтаксис регулярних виразів. Конкретно:
(^|\s)
: збігається з початком рядка ( ^
) або пробілом ( \s
).(\.|source)\s+
: відповідає будь-якому буквальному .
символу ( \.
) або слову source
, але тільки якщо за ними дотримуються один або кілька символів пробілу.Ось що це дає мені в моїй системі:
$ 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
Як ви бачите, однак, це надрукує всю відповідну лінію. Що нас насправді цікавить - це список назв файлів, які називаються, а не лінія, яка їх викликає. Ви можете отримати ці, більш складні, регулярні вирази:
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
Прапор пригнічує друк імен файлів , де був знайдений матч, який grep
робить за замовчуванням , коли велено шукати через кілька файлів. В -o
означає «друкувати тільки на відповідну ділянку лінії». Додатковими матеріалами, доданими до регулярного виразу, є:
\K
: ігноруйте що-небудь відповідне до цього моменту. Це фокус PCRE, який дозволяє використовувати складний регулярний вираз, щоб знайти свою відповідність, але не включати відповідну частину при використанні -o
прапора grep's .У моїй системі наведена вище команда повернеться:
$ 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
Зауважте, що у мене, як правило, використовується .
пробіл, який не використовується для пошуку джерел, але це тому, що у мене є псевдонім, який називає іншу мову, а не bash. Ось що дає дивне $a*100/$c
і ")\n"'
у висновку вище. Але це можна ігнорувати.
Нарешті, ось як скласти все це разом і шукати ім’я функції у всіх файлах за замовчуванням та у всіх файлах, за якими розміщуються файли за замовчуванням:
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
}
Додайте ці рядки до свого, ~/.bashrc
і ви зможете запустити (я використовую fooBar
як ім'я функції прикладу):
grep_function fooBar
Наприклад, якщо я маю цей рядок у своєму ~/.bashrc
:
. ~/a
А файл ~/a
такий:
$ cat ~/a
fooBar(){
echo foo
}
Я мушу знайти це за допомогою:
$ grep_function fooBar
/home/terdon/a:fooBar(){
+=
array+="foo"
додавання рядка foo
до 1-го елемента масиву?
Звичайні для кожного користувача dotfile bash
читає це ~/.bashrc
. Однак це може дуже добре джерело інших файлів, я, наприклад, люблю зберігати псевдоніми та функції в окремих файлах, що називаються ~/.bash_aliases
і ~/.bash_functions
, що робить їх набагато простіше. Ви можете шукати .bashrc
для source
команд з:
grep -E '(^\s*|\s)(\.|source)\s' /home/USERNAME/.bashrc
Коли у вас є список створених користувачем файлів, ви можете шукати в них та користувачі .bashrc
одним grep
викликом, наприклад, для функції foo
для моєї настройки:
grep foo /home/USERNAME/.bash{rc,_aliases,_functions}