Вопрос или проблема
…то есть, есть ли способ, с помощью которого я могу прочитать полную команду, которая выполняется, в процессе её выполнения? Вот искусственный пример, который, как мне кажется, делает вопрос ясным:
function showOwnEvaluation {
local evaluatingCommand=????
[[ "$evaluatingCommand" =~ ^showOwnEvaluation ]] && echo "Original Function"
}
alias sOE='showOwnEvaluation'
$ showOwnEvaluation 123
# Вывод: Original Function
$ sOE 123
# Вывод:
В большинстве случаев возможность выполнить echo "$(!-1)"
для текущей активной команды? Или echo "$(!0)"
, если хотите?
То, что я хотел бы здесь достичь, это: если я присваиваю результат раскрытия переменной:
someVar=$(myFunc)
…я хотел бы иметь возможность изменить ответ из myFunc
на основе имени переменной, в которую он присваивается. Я просто не могу понять, как получить часть выражения someVar=
, если это вообще возможно СДЕЛАТЬ (без установки полной эмуляции над терминалом и мониторинга всего ввода-вывода, конечно).
Я понимаю, что это может показаться бессмысленным желанием, но у меня действительно есть обоснованная причина. Я не уверен, возможно ли это вообще.
Ответ или решение
В Bash 5.2+ возникает интересный вопрос: можно ли как-то получить текущее выполняемое командное выражение в реальном времени. Этот запрос, безусловно, выходит за рамки типичного использования командной оболочки Bash, и вызывает интерес именно уникальностью своего применения. Мы попытаемся детально проанализировать эту задачу, основываясь на ее контексте и доступных в Bash инструментах.
Теория
Для начала, давайте посмотрим, что же мы имеем. В большой степени командные оболочки, и Bash в частности, были разработаны для выполнения команд без предоставления интерфейса для анализа или считывания этих команд в их текущем нестабильном состоянии. Bash — это, прежде всего, интерпретатор, целью которого является прием, интерпретация и выполнение команд, но не предоставление обратной информации о процессе выполнения команд.
С другой стороны, существуют встроенные или дополнительные утилиты и функции, которые предоставляют контекст выполнения, такие как BASH_COMMAND
, BASH_LINENO
, и FUNCNAME
. Однако они дают информацию только в более ограниченном и статическом контексте, например, текущая строка или функция, но не саму команду в процессе оценки.
Пример
Чтобы проиллюстрировать это, рассмотрим элементы, которые предоставляет Bash:
-
Переменная
BASH_COMMAND
: Эту переменную можно использовать для получения текущей выполняемой команды, но это будет не совсем то, что запрашивает ваш пример – завладевание всей командой на лету, как это делаетBASH_COMMAND
, происходит уже после ее оценки. То есть вы не получите полный ввод до его завершения. -
Переменная
PROMPT_COMMAND
: Этот механизм может использоваться для выполнения сценариев перед отображением приглашения, но это не дает содержимого команды до ее исполнения. -
Трассировка с использованием
set -x
: Это может помочь выяснить, какой код выполняется в сценариях, но это скорее отладочный инструмент, чем интерактивный.
Применение
Теперь, имея представление о теории, перейдем к применимости. Задача, чтобы функция могла принимать различные действия в зависимости от контекста ее вызова, является действительно сложной. В вашем случае вы хотите, чтобы функция была информирована о том, куда выходит ее вывод или какой контекст вызова ее окружает.
Возможные подходы:
-
Хуки оболочки:
Несмотря на то, что Bash не предоставляет прямой механизм для реализации данной задачи, существуют методы, которые могут помочь. Некая эмуляция может быть достигнута за счет анализа командной истории или использования исходного трассировочного механизма, но с предупреждением, что это будет неэффективным и неточным. -
Инструменты внешнего отслеживания:
Можно рассмотреть использование инструментов, таких какstrace
в Unix-системах, для отслеживания системных вызовов и сигналов, хотя этот подход подходит только для глубокого отладки и требует продвинутого уровня доступа и опыта в работе с системой. -
Изменение архитектуры скрипта:
Возможно, лучший подход — это переосмысление архитектуры, с возможностью явной передачи контекста в функцию. Например, вы можете использовать дополнительные параметры для ваших функций, представляющих предполагаемый контекст их вызова.
function myFunc {
local targetVar=$1
# Прочая логика функции с учетом 'targetVar'
}
result=$(myFunc "someVar")
Эта стратегия позволяет вам контролировать контекст выполнения и действия функции, тем самым отступая от попытки непосредственно капсулировать текущую команду.
Заключение
Концепция выполнения команд с возможностью нахватить полный ввод в процессе исполнения в Bash вызывает как технический интерес, так и много сложностей. Bash, в его текущей форме, не предоставляет механизмов для выполнения этого задания в явном, управляемом виде. Рекомендуется обратить внимание на архитектурные изменения и использовать доступные разнообразные параметры, чтобы достигнуть требуемого поведения ваших скриптов, либо интегрировать с более мощными инструментами системного отслеживания и журналирования для более сложных сценариев.