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

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

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

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

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

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

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

14
задан 8 December 2017 в 19:58

2 ответа

Вы можете немного адаптировать свой метод. Вместо непосредственного подключения к 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.
  • [Тысяча сто тридцать одна]
12
ответ дан 8 December 2017 в 19:58

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

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 |
                ||     ||
16
ответ дан 8 December 2017 в 19:58

Другие вопросы по тегам:

Похожие вопросы: