例如,如果我有一個
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 的解決方案。