В bash: обрабатывать каждую командную строку без использования отладочной ловушки?

2

У меня есть сложный механизм, встроенный в мою среду bash, который требует выполнения пары сценариев при создании приглашения, а также когда пользователь нажимает клавишу ввода, чтобы начать обработку команды. Я приведу упрощенное описание:

Ловушка отладки делает это довольно ограниченным способом: она срабатывает каждый раз, когда выполняется оператор.

trap 'echo $BASH_COMMAND' DEBUG  # example only

К сожалению, это означает, что когда я набираю это:

sleep 1; sleep 2; sleep 3

вместо обработки $ BASH_COMMAND, содержащей всю строку, я получаю три сна в трех разных ловушках. Еще хуже:

sleep 1 | sleep 2 | sleep 3

запускает все три при настройке канала - еще до того, как сон 1 начнет выполняться, вывод может привести вас к мысли, что сон 3 запущен.

Мне нужен способ выполнить скрипт в самом начале, обрабатывая всю команду, и я бы предпочел, чтобы он не запускался при запуске команды prompt, но я могу справиться с этим, если нужно.

Sniggerfardimungus
источник
Хороший вопрос. Но больше ориентирован на программирование, поэтому он должен идти в StackOverflow.
JakeGould

Ответы:

3

Не очень красиво, но если вам это действительно нужно, вы можете использовать PROMPT_COMMANDв дополнение к отладочной ловушке, чтобы избавиться от дополнительных вызовов:

trap 'debug_hook' DEBUG

debug_hook()
{ 
  [ -n "$debug_hook_on" ] || return 
  debug_hook_on="" 
  echo hook             # cmds to run ...
}

PROMPT_COMMAND='debug_hook_on=1'

В настоящее время:

$ echo 1 ; echo 2 | cat
hook
1
2

У нас все еще нет доступа ко всей строке ввода: $BASH_COMMANDпросто echo 1.


Другая идея, вдохновленная этой статьей, заключается в использовании привязок readline для получения доступа ко всей строке:

$ bind -x '"\C-o":hook'
$ hook(){ echo "hook: $READLINE_LINE";  }
$ bind 'RETURN: "\C-o\n"'

Теперь это работает:

hook: echo 1; echo 2
$ echo 1; echo 2
1
2

Однако следует помнить одну вещь: для многострочного ввода он будет вызываться один раз для каждой строки, что может быть не тем, что вы хотите (тогда можно было бы использовать комбинацию обоих подходов).

lemonsqueeze
источник
Я в конечном итоге завел историю вызовов из обработчика ловушек и взял самую последнюю командную строку. Попутно я НИКОГДА не учил фоновый процесс в обработчике ловушек. Даже если вы откажетесь от процесса, ловушка не вернется, пока не завершится подпроцесс.
Sniggerfardimungus