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

Взял его в магазин, он был исправлен.

13
задан 8 December 2017 в 20:58

6 ответов

Вы можете немного адаптировать свой метод. Вместо прямого подключения к 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 обработку [ f10] на входе специально (поэтому, например, \n считывается как \n и не преобразуется в символ новой строки). -d '' - это способ сказать read читать до символа NUL. Таким образом, вся вещь проходит через ввод в разделах с разделителями NUL, сохраняя при этом содержимое ввода как можно больше. if [[ -n $line ]]; then ... fi; done - действовать, только если введенный ввод не пуст. echo; printf "%s\n" "$line" | cowsay; - печатает ведущую пустую строку, так что выход cowsay не сталкивается с приглашением, а затем посылает введенный до сих пор вход в cowsay. printf является более надежным и безопасным, чем echo.
12
ответ дан 22 May 2018 в 15:33
  • 1
    Это потрясающе, спасибо большое! Не могли бы вы объяснить немного больше, как работает линия >(while IFS= read ...)? – M. Becerra 8 December 2017 в 16:12
  • 2
    очень интересно, спасибо снова! :) – M. Becerra 8 December 2017 в 16:28
  • 3
    Поскольку у моего подсказки есть линия в нем, вывод cowsay делает столкновение со второй частью его - возможно, также может быть установлено приглашение на что-то не отвлекающее? – dessert 8 December 2017 в 16:29

Вы можете немного адаптировать свой метод. Вместо прямого подключения к 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
ответ дан 18 July 2018 в 01:36

Вы можете немного адаптировать свой метод. Вместо прямого подключения к 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
ответ дан 24 July 2018 в 17:25

Вы можете trap и использовать сигнал DEBUG баха.

trap '$BASH_COMMAND | cowsay' DEBUG

Пример run

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

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

$ shopt -s extdebug
$ trap '$BASH_COMMAND | cowsay; false' DEBUG
$ echo "AU is awesome!"
 __________________
< "AU is awesome!" >
 ------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
13
ответ дан 22 May 2018 в 15:33
  • 1
    shopt -s extdebug, а затем ненулевое значение выхода после того, как обработчик ловушки предотвратит запуск команды. – ilkkachu 9 December 2017 в 03:30
  • 2
    либо запустить false, либо поместить всю логику обработки ловушки в функцию, а затем return 1. (вы не можете return с основного уровня ловушки, а exit выйдет из оболочки) – ilkkachu 9 December 2017 в 03:49
  • 3
    @ilkkachu Точно так же, как я пытался, наоборот, но false, безусловно, самое легкое решение здесь. – dessert 9 December 2017 в 03:50

Вы можете trap и использовать сигнал DEBUG баха.

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

Пример run

$ 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
ответ дан 18 July 2018 в 01:36

Вы можете trap и использовать сигнал DEBUG баха.

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

Пример run

$ 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
ответ дан 24 July 2018 в 17:25

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

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