Как передать каждую команду, переданную оболочке?

14

Я хотел бы отредактировать мой .bashrc так, чтобы каждая команда, выполняемая в оболочке, передавалась по чему-либо, например:

 $ sudo apt update
  _________________
< sudo apt update >
 -----------------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

Мне удалось что-то довольно похожее, но не совсем:

$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
 _______
< Hello AU! >
 -------
    \   ^__^
     \  (oo)\_______
        (__)\       )\/\
            ||----w |
            ||     ||

Это не желаемый результат, так как это происходит только после выхода из текущей оболочки.

Это в основном для развлечения / обучения.

М. Бесерра
источник
Использование -nфлага для cowsayполезно; это заставляет это сохранять пробел.
августа

Ответы:

12

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

exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
PROMPT_COMMAND='printf "\0"'

Здесь я использую символ ASCII NUL. Вы можете использовать что-то еще, что вряд ли появится в выводе команды.

Это напечатает после приглашения, поэтому вывод будет уродливым:

$ export LC_ALL=C
$ exec > >(while IFS= read -d '' -r line; do if [[ -n $line ]]; then echo; printf "%s\n" "$line" | cowsay; fi; done)
$ PROMPT_COMMAND='printf "\0"'
$ ls
$
 ______________________________________
/ Desktop Documents Downloads Music    \
| Pictures Public Templates Videos
\ examples.desktop                     /
 --------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

$ echo foo
$
 ______
< foo  >
 ------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

Обратите внимание, что это сломает любую команду, которая пытается выполнить сложный вывод или имеет текстовый пользовательский интерфейс (например, редакторы командной строки, пейджеры и т. Д.).

Предполагая, что вы уже знаете, что exec > >(...)делает, часть в замене процесса:

  • while IFS= read -d '' -r line; do ... done: это довольно распространенная идиома для чтения данных, разделенных символом ASCII NUL:

    • IFS= устанавливает IFS в пустую строку, что отключает разделение полей
    • -rпредотвращает readобработку \во вводе специально ( \nнапример, читается как \nи не преобразуется в символ новой строки).
    • -d ''это способ сказать, readчтобы прочитать, пока символ NUL

    Таким образом, все циклически повторяется над вводом в разделах, разделенных NUL, при максимально возможном сохранении содержимого ввода.

  • if [[ -n $line ]]; then ... fi; done - Действовать только в том случае, если прочитанный ввод не является пустым.
  • echo; printf "%s\n" "$line" | cowsay;- выведите начальную пустую строку, чтобы вывод cowsay не конфликтовал с подсказкой, а затем отправьте введенные данные до сих пор в cowsay. printfнадежнее и безопаснее, чем echo.
Мур
источник
1
Как моя подсказка имеет LINEBREAK в нем Cowsay выход делает столкновение со второй частью - возможно также установить запрос на что - то , не отвлекаясь?
десерт
16

Вы можете trapи злоупотреблять DEBUGсигналом Баша:

trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG

Пример запуска

$ trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
AU is awesome!

Однако это все равно выполнит команду позже. Благодаря ilkkachu я нашел способ обойти это:

$ shopt -s extdebug
$ trap 'bash -c "$BASH_COMMAND" | cowsay; false' DEBUG
$ echo "AU is awesome!"
 __________________
< AU is awesome! >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Десерт
источник