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 запущен.

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

1 ответ1

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .