M. *_*rra 14 command-line bash bashrc
我想编辑我的 .bashrc 以便在 shell 上执行的每个命令都通过管道传输到某些东西,例如:
$ sudo apt update
_________________
< sudo apt update >
-----------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Run Code Online (Sandbox Code Playgroud)
我已经管理了一些相当相似的东西,但不完全是:
$ bash
$ exec > >(cowsay)
$ echo "Hello AU!"
$ exit
_______
< Hello AU! >
-------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Run Code Online (Sandbox Code Playgroud)
这不是想要的结果,因为它只在退出当前 shell 后发生。
它主要用于娱乐/学习目的。
des*_*ert 16
你可以trap滥用 bash 的DEBUG信号:
trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
Run Code Online (Sandbox Code Playgroud)
$ trap 'bash -c "$BASH_COMMAND" | cowsay' DEBUG
$ echo "AU is awesome!"
__________________
< AU is awesome! >
------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
AU is awesome!
Run Code Online (Sandbox Code Playgroud)
但是,这之后仍会执行命令。感谢ilkkachu我找到了解决方法:
$ shopt -s extdebug
$ trap 'bash -c "$BASH_COMMAND" | cowsay; false' DEBUG
$ echo "AU is awesome!"
__________________
< AU is awesome! >
------------------
\ ^__^
\ (oo)\_______
(__)\ )\/\
||----w |
|| ||
Run Code Online (Sandbox Code Playgroud)
mur*_*uru 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"'
Run Code Online (Sandbox Code Playgroud)
在这里,我使用的是 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 |
|| ||
Run Code Online (Sandbox Code Playgroud)
请注意,这将破坏任何尝试复杂输出或具有文本用户界面的命令(想想命令行编辑器、寻呼机等)。
假设您已经知道是什么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。