例如,如果我有一个
alias dbmigrate='rails db:migrate'
是否有一种模式或简单的方法可以在 Bash 和 Zsh 中进行配置,以便当我在 shell 中键入时:
$ dbmigrate # press Enter
它会在运行之前回显别名扩展为什么?
答案1
在巴什,有alias-expand-line
和history-and-alias-expand-line
readline 函数,但默认情况下它们不绑定到任何键。您可以自己绑定它们 - 例如Control-T
:
bind '"\C-T": history-and-alias-expand-line'
尝试绑定Enter
自身会很混乱,因为并非任何时候您按下Enter
都会执行命令(例如,当它是不完整的管道时,等等)。
还有一个DEBUG
陷阱,但是确定该命令是否实际上是由用户输入的(例如,不是从PROMPT_COMMAND
中的命令替换启动的PS1
),以及它是否是别名扩展的,这将是很棘手的;但如果你同意打印任何执行前的命令:
trap 'echo "> $BASH_COMMAND"' DEBUG
bash$ pwd
> pwd
在桀骜,您可以简单地定义一个preexec
函数,如果与用户输入的命令不同,则打印扩展命令:
preexec(){ [ $1 != $2 ] && print -r "> $2" }
zsh$ j
> jobs
但请注意,如果强制扩展别名,某些别名+历史记录技巧将无法正常工作。例如,我c
在 bash 中有一个别名来执行诸如 之类的计算c 3.17 * 4.2
,而不必转义*
,(
等:
alias c='_c=$(fc -nl -0); bc -l <<<${_c#*c} #'
一旦 readline 展开它,历史记录中的当前行(由 返回的行fc -nl -0
)将是扩大,不是原来的命令,一切都会崩溃。
答案2
别名只是简单的替换。如果您想做一些更奇特的事情,例如在运行命令之前打印一条消息,您需要更强大的东西:函数。如果您希望定义看起来像别名定义,则可以定义一个定义函数的函数。
function verbose_alias {
local name=${1%%=*} expansion=${1#*=}
eval "function $name {
printf >&2 '%s is an alias for %s\\n' \"$name\" \"$expansion\";
$expansion \"\$@\";
}"
}
verbose_alias dbmigrate='rails db:migrate'
答案3
POSIX 要求set
命令有这个选项
-x
shell 应在扩展命令之后和执行命令之前向标准错误写入每个命令的跟踪。未指定是否跟踪关闭跟踪的命令。
https://pubs.opengroup.org/onlinepubs/009604499/utilities/set.html
因此您可以在任何兼容的 shell 上使用set -x
或。set -o xtrace
在 bash 中,您可以在手册页中看到这一点:
-x
展开每个简单命令、for 命令、case 命令、select 命令或算术 for 命令后,显示 PS4 的展开值,后跟该命令及其展开参数或关联的单词列表。
xtrace
与...一样
-x
。
zsh 也有类似的选项set
内置
XTRACE(
-x
,克什-x
:)执行命令时打印命令及其参数。
您还可以-x
在执行脚本或命令时指定选项
bash -x -c "echo This will be printed before running; ll"
bash -x script-to-be-debugged.sh
zsh -x -c "...; 3; md did-you-see-the-aliases"
zsh -x buggy-script.sh
请注意,它还扩展了每个提示之前和之后运行的命令,因此在许多情况下可能并不理想,例如当您git
在 PS1 中使用变量时。在我干净的 Ubuntu VM 中,仅打印出正在运行的命令
也可以看看有什么set -x
作用?
另一个选项是set -v
orset -o verbose
在打印之前不扩展变量
答案4
bash 默认情况下不提供这种帮助。
默认情况下可用的两个相关函数是:
shopt -s histverify
如果设置并且正在使用 readline,则历史替换的结果不会立即传递到 shell 解析器。相反,生成的行将加载到读取行编辑缓冲区中,从而允许进一步修改。
它解决了按下时的操作部分Enter
,但仅在命令行上具有历史扩展。例如:
$ shopt -s histverify
$ echo "this is a test"
This is a test
$ echo !!
$ echo echo "this is a test" <---- expanded by the simple use of enter!!
- 阅读线
shell-expand-line
外壳扩展线 (MCe)
像 shell 一样展开该行。这将执行别名和历史扩展以及所有 shell 字扩展。有关历史扩展的描述,请参阅下面的历史扩展。
这正是您要求完成的,但使其发挥作用的关键是Ctrl- Alt-e
shell-expand-line
抱歉,我不知道与 Enter 和executes 一起使用的解决方案。