1. 程式人生 > >linux系統下的實現我們自己的命令列補全

linux系統下的實現我們自己的命令列補全

當進入某個目錄下面的時候,如果忘記名字或者怎麼進入的,可以連按兩下tab鍵,這個時候linux會為我們列出來到底有哪些目錄,哪些檔案。

而這不是linux系統天生就有的,而是需要complete這個自動補全工具。我們用的linux大多數都已經安裝。

因為目前我維護10幾臺伺服器,經常會進行登陸。雖然我之前使用了別名的方式,但依然不夠靈活,時間長了還是會忘記伺服器的名字,通常還需要看一下記錄別名的檔案。這是很麻煩的一件事情。

於是我google了一下,發現網上關於complete的資料挺多的。我完成了關於我伺服器的命令提示,同時也完成了ssh,scp的命令列提示。這裡做一個記錄,供大家參考。

直接上結果:

complete -W "$(echo $(grep '^ssh ' .bash_history | sort -u | sed 's/^ssh //'))" ssh
complete -W "$(echo $(grep '^scp ' .bash_history | sort -u | sed 's/^scp //'))" scp

正常情況下,我們在鍵盤敲入ssh 或者scp,系統是不會給你補全你有哪些登陸或者拷貝情況的。這個時候,如果能從歷史裡面獲取之前的登陸記錄,就會特別的方便。

先看 "$(echo $(grep "^ssh " .bash_history | sort -u | sed 's/^ssh //'))"

這個裡面就是執行了獲取歷史命令裡面以ssh開頭的,排序並去重,然後去掉開頭的ssh.

-W 的意思是 wordlist 分割 wordlist 中的單詞,作為候選的補全結果

而最後的ssh,就是執行ssh後,觸發前面的匹配規則。

當然,scp也是如此。那如果一堆需要管理的伺服器呢?

我們可以手寫的方式,一個一個的寫進去,這個完全沒毛病。但是,如果增加了一個伺服器,或者你需要直接連線某個資料庫或者mongodb/redis呢?可能每次都得新增,還比較麻煩。

這裡使用case,esac就是特別好的解決辦法。
舉個例子

我在我的家目錄下建立了一個檔案,名字是goto.
裡面是一個case語句。

#!/bin/bash
case $1 in
    a)
    ssh [email protected] ;;
    b)
    ssh [email protected] ;;
    c)
    ssh [email protected] ;;
esac

寫完之後,chmod +x goto. 讓檔案可以執行。然後進入到/etc/bash_completion.d/下,建立一個goto.bash檔案,然後寫入

_goto() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local pro=$(echo $(grep ")" /home/guo/goto | cut -f 1 -d ")" ))
    COMPREPLY=( $(compgen -W "$pro" -- $cur ) )
}
complete -F  _goto goto

其實這個可以像上面的ssh,scp一樣寫到shell裡面,但是這裡正常情況下一個這些這裡。因為/etc/bash_completion.d是專門管理提示指令碼的。

complete -F _goto裡面, -F 的意思是function 執行shell 函式,函式中生成COMPREPLY作為候選的補全結果。
這裡goto就是執行_goto這個函式。 而函式裡面的意義,建議大家參考這篇博文

如果寫到bashrc裡面,可以這麼寫:

complete -W "$(echo $(grep ")" ~/goto | cut -f 1 -d ")" ))" goto

參考:

https://blog.csdn.net/smilefyx/article/details/44654487
https://www.coder4.com/archives/4086
https://www.imooc.com/article/1457
https://github.com/Jisuanke/tech-exp/issues/15
https://askubuntu.com/questions/443186/whats-the-use-of-complete-command
https://www.linuxjournal.com/content/more-using-bash-complete-command