Как я могу найти, где определена определенная функция bash?
28
Есть много функций, которые можно использовать в оболочке Bash. Их определения могут быть перечислены set, но как найти, в каких файлах определены определенные пользователем функции?
Если установлено при вызове оболочки или в файле запуска оболочки, организуйте выполнение профиля отладчика до запуска оболочки, идентично
--debuggerпараметру. Если установлено после вызова, поведение, предназначенное для использования отладчиками, включено:
-FВариант к declareвстроенной команде (см Bash Встроенные командам ) отображает имя исходного файла и номер строки , соответствующий каждое имя функции , подаваемое в качестве аргумента.
Это отличное и простое решение. Что же касается вашего примера, это даже не требуется , чтобы начать новую оболочку: shopt -s extdebug; declare -Ff quote; shopt -u extdebug.
Ярно
2
@ Ярно, ну, вопреки моему имени, я использую Zsh. Вот почему я начал новую оболочку. : D
bashity mcbashface
Есть ли подобный метод, чтобы найти места объявления псевдонимов ?
ФедонКадифели
@ Fedon мой замысловатый и сложный подход ниже должен работать.
Тердон
1
Вы могли бы сделать эту функцию следующим образом: find_function()( shopt -s extdebug; declare -F "$@"; ). С паренами в теле функции, он выполняется в подоболочке, и изменение в shopts не влияет на вызывающего. И -f, кажется, не нужно.
wjandrea
15
Это на самом деле сложнее, чем кажется на первый взгляд. Какие файлы читаются вашей оболочкой, зависит от того, какую оболочку вы используете в данный момент. Является ли это интерактивным или нет, будь то оболочка для входа в систему или не для входа в систему и какая комбинация вышеперечисленного. Чтобы выполнить поиск по всем файлам по умолчанию, которые могут быть прочитаны различными оболочками, вы можете сделать это (изменить $functionNameфактическое имя искомой функции):
Это, вероятно, нуждается в некотором объяснении. -PПозволяет Perl Compatible Regular Expressions (PCRE) , которые позволяют нам использовать некоторые любитель синтаксис регулярных выражений. В частности:
(^|\s): соответствует либо началу строки ( ^), либо пробелу ( \s).
(\.|source)\s+: соответствует буквальному .символу ( \.) или слову source, но только в том случае, если за ними следует один или несколько пробельных символов.
Как вы можете видеть, однако, это напечатает всю совпавшую линию. Что нас действительно интересует, так это список имен файлов, а не строка, которая их вызывает. Вы можете получить те с этим, более сложным, регулярным выражением:
Этот -hфлаг подавляет печать имен файлов, в которых найдено совпадение, что grepпо умолчанию выполняется при поиске в нескольких файлах. В -oозначает «печатать только на соответствующий участок линии». Дополнительный материал, добавленный в регулярное выражение:
\K: игнорировать что-либо подходящее до этого момента. Это трюк PCRE, который позволяет вам использовать сложное регулярное выражение для поиска соответствия, но не включать эту совпадающую часть при использовании -oфлага grep .
Обратите внимание, что у меня есть случай использования .пробела, который не используется для поиска источников, но это потому, что у меня есть псевдоним, который вызывает другой язык, а не 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"fidone}
Добавьте эти строки к вашему, ~/.bashrcи вы сможете запустить (я использую fooBarв качестве примера имя функции):
grep_function fooBar
Например, если у меня есть эта строка в моем ~/.bashrc:
Ваше решение является отличным учебным примером сценариев, но я считаю, что решение bashity mcbashface проще.
Ярно
@jarno, и это намного, намного проще! :)
тердон
Поддержка массивов+=
Д.Бен Нобл
@ D.BenKnoble они делают? Вы имеете в виду кроме array+="foo"добавления строки fooк 1-му элементу массива?
тердон
1
@ D.BenKnoble спасибо! Я не знал, что массивы bash поддерживают эту запись!
Тердон
2
Обычные для каждого пользователя dotfile bashчитает это ~/.bashrc. Тем не менее, он вполне может быть источником других файлов, например, мне нравится хранить псевдонимы и функции в отдельных файлах , которые называются ~/.bash_aliasesи ~/.bash_functions, что значительно упрощает их поиск. Вы можете искать .bashrcдля sourceкоманд с:
Когда у вас есть список созданных пользователем файлов, вы можете искать их и пользователя .bashrcодним grepвызовом, например, для функции fooдля моей настройки:
Ответы:
Включите отладку. Из руководства Bash :
Пример:
И действительно:
источник
shopt -s extdebug; declare -Ff quote; shopt -u extdebug
.find_function()( shopt -s extdebug; declare -F "$@"; )
. С паренами в теле функции, он выполняется в подоболочке, и изменение в shopts не влияет на вызывающего. И-f
, кажется, не нужно.Это на самом деле сложнее, чем кажется на первый взгляд. Какие файлы читаются вашей оболочкой, зависит от того, какую оболочку вы используете в данный момент. Является ли это интерактивным или нет, будь то оболочка для входа в систему или не для входа в систему и какая комбинация вышеперечисленного. Чтобы выполнить поиск по всем файлам по умолчанию, которые могут быть прочитаны различными оболочками, вы можете сделать это (изменить
$functionName
фактическое имя искомой функции):Если это не сработает, вы можете вызывать файл не по умолчанию, используя
.
его или его псевдонимsource
. Чтобы найти такие случаи, запустите:Это, вероятно, нуждается в некотором объяснении.
-P
Позволяет Perl Compatible Regular Expressions (PCRE) , которые позволяют нам использовать некоторые любитель синтаксис регулярных выражений. В частности:(^|\s)
: соответствует либо началу строки (^
), либо пробелу (\s
).(\.|source)\s+
: соответствует буквальному.
символу (\.
) или словуsource
, но только в том случае, если за ними следует один или несколько пробельных символов.Вот что это дает мне в моей системе:
Как вы можете видеть, однако, это напечатает всю совпавшую линию. Что нас действительно интересует, так это список имен файлов, а не строка, которая их вызывает. Вы можете получить те с этим, более сложным, регулярным выражением:
Этот
-h
флаг подавляет печать имен файлов, в которых найдено совпадение, чтоgrep
по умолчанию выполняется при поиске в нескольких файлах. В-o
означает «печатать только на соответствующий участок линии». Дополнительный материал, добавленный в регулярное выражение:\K
: игнорировать что-либо подходящее до этого момента. Это трюк PCRE, который позволяет вам использовать сложное регулярное выражение для поиска соответствия, но не включать эту совпадающую часть при использовании-o
флага grep .В моей системе приведенная выше команда вернет:
Обратите внимание, что у меня есть случай использования
.
пробела, который не используется для поиска источников, но это потому, что у меня есть псевдоним, который вызывает другой язык, а не bash. Это то, что дает странный$a*100/$c
и")\n"'
в выводе выше. Но это можно игнорировать.Наконец, вот как собрать все это вместе и найти имя функции во всех файлах по умолчанию и во всех файлах, которые ваши файлы по умолчанию поставляют:
Добавьте эти строки к вашему,
~/.bashrc
и вы сможете запустить (я используюfooBar
в качестве примера имя функции):Например, если у меня есть эта строка в моем
~/.bashrc
:И файл
~/a
:Я должен найти это с:
источник
+=
array+="foo"
добавления строкиfoo
к 1-му элементу массива?Обычные для каждого пользователя dotfile
bash
читает это~/.bashrc
. Тем не менее, он вполне может быть источником других файлов, например, мне нравится хранить псевдонимы и функции в отдельных файлах , которые называются~/.bash_aliases
и~/.bash_functions
, что значительно упрощает их поиск. Вы можете искать.bashrc
дляsource
команд с:Когда у вас есть список созданных пользователем файлов, вы можете искать их и пользователя
.bashrc
однимgrep
вызовом, например, для функцииfoo
для моей настройки:источник