用过bash的人,可能都对TAB自动补全功能有印象吧,按一下“TAB“键就自动帮你把命令或者文件名补全,确实好用。
这个应该是bash解析用户输入的时候,加上这个自动补全的功能的。方便的地方是bash提供的内置命令complete允许你对这个功能进行自定义扩展。 比如
complete -F _my_host my_ssh 就会指定 my_ssh这个名字的自动完成由 _my_host 这个函数去处理
比如我在 .bashrc 后面加上下面这个代码之后
----------------------------------------------
_my_host() {
local HOST cur
COMPREPLY=()
_get_comp_words_by_ref cur
HOST="local test test2 devolop"
COMPREPLY=( $( compgen -W "$HOST" -- "$cur" ) )
}
complete -F _my_host my_ssh
alias egenera_ssh=/home/widebright/桌面/my_ssh.pl
-----------------------------------------------
这样设置之后,在终端再输入自己的自定义命令my_ssh 然后按TAB键,就会自动出来自己预先定义的host主机名字了
---------------
widebright@:~/桌面$ my_ssh
local test test2 devolop
-------------------------
其中COMPREPLY 是Bash的内置变量,一个数组,返回结果到这里去后,bash就是读取这个变量作为自动完成的匹配组合的。
compgen -W "$HOST" -- "$cur" 命令根据当前的输入"$cur" 返回$HOST中匹配的部分。compgen也是内置命令的。_get_comp_words_by_ref 是预定义函数,不过自己从COMP_WORDS 和COMP_CWORD两个预定义变量中去读取当前输入信息。COMP_WORDS表示当前命令输入参数的单词数组,COMP_CWORD表示当前光标的 位置。参考一个例子
------------------------
_xm()
{
local cur prev opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
#
# The basic options we'll complete.
#
opts="console create list"
#
# Complete the arguments to some of the basic commands.
#
case "${prev}" in
console)
local running=$(for x in `xm list --long | grep name|grep−vDomain−0|awk′print$2′|tr−d`; do echo ${x} ; done )
COMPREPLY=( $(compgen -W "${running}" -- ${cur}) )
return 0
;;
create)
local names=$(for x in `ls -1 /etc/xen/*.cfg`; do echo ${x/\/etc\/xen\//} ; done )
COMPREPLY=( $(compgen -W "${names}" -- ${cur}) )
return 0
;;
*)
;;
esac
COMPREPLY=($(compgen -W "${opts}" -- ${cur}))
return 0
}
complete -F _xm xm
------------------------------------
complete 命令的和预定义的详细说明可以参考bash的文档。
启动complete -p 可以查看bash已经定义的命令的自动完成函数。
pack.sh 的
#!/bin/bash
####set board
thisXwDevicePath="`echo $DEVICE`"
thisXwBoard=chiphd
XwLicheeConfig=
cp $DEVICE/wifi_efuse_8189e.map $OUT/system/etc/wifi/ && echo -e "cp wifi_efuse_8189e.map"
if [ -f $thisXwDevicePath/configs_chiphd/do_chiphd.sh ]; then
NowCustomFlagFile=$thisXwDevicePath/configs_chiphd/NowCustom.sh
if [ ! -f $NowCustomFlagFile ]; then
bash $thisXwDevicePath/configs_chiphd/do_chiphd.sh
fi
NowCustomCfg=`sed -n '1p' $NowCustomFlagFile`
thisXwBoard=$(echo $NowCustomCfg | awk -F/ '{print $(NF-2)"-"$(NF-1)}')
XwLicheeConfig=${NowCustomCfg%/*}/lichee
#cat $DEVICE/configs_chiphd/custom/NowCustom.sh | awk -F/ '{print $(NF-2) "/" $(NF-1)}'`
fi
thisCfgDir=`echo $ANDROID_BUILD_TOP/../lichee/tools/pack/chips/*/configs/android`
## for a10
if [ ! -d "$thisCfgDir" ]; then thisCfgDir=`echo $ANDROID_BUILD_TOP/../lichee/tools/pack/chips/*/configs/crane`; fi
## for a3x-4.4
if [ ! -d "$thisCfgDir" ]; then thisCfgDir=`echo $ANDROID_BUILD_TOP/../lichee/tools/pack/chips/sun8iw5p1/configs`; fi
## copy .fex file
if [ "$XwLicheeConfig" -a -d "$XwLicheeConfig" ]; then
#echo $thisCfgDir/$thisXwBoard
if [ ! -d $thisCfgDir/$thisXwBoard ]; then mkdir $thisCfgDir/$thisXwBoard; fi
cp -r --force ${XwLicheeConfig}/configs/*.* $thisCfgDir/$thisXwBoard/
echo "done : cp -r --force ${XwLicheeConfig}/configs/*.* $thisCfgDir/$thisXwBoard/"
else
echo "XwLicheeConfig = ${XwLicheeConfig}"
fi
#### repo tag file to system.img when $1 = --tag
XwImgAndroidTagFunc="$thisXwDevicePath/../zzzzz-chiphd/xw_img_create_android_tag.sh"
if [ -f $XwImgAndroidTagFunc ]; then
$XwImgAndroidTagFunc $1
fi
#### prepare for rename-img-file
XwImgRenameFunc="$thisXwDevicePath/../zzzzz-chiphd/xw_img_rename.sh"
if [ -f $XwImgRenameFunc ]; then
$XwImgRenameFunc --new && echo "auto rename img file later ..."
fi
CHIPHD_NEED_REBUILD_SYS_IMG=false
#wifi efuse
wifi_efuse_src=$thisXwDevicePath/configs_chiphd/wifi_efuse/wifi_efuse_8189e_for_MB1019Q5.map
wifi_efuse_dst=$OUT/system/etc/wifi/wifi_efuse_8189e.map
if [ ! -f $wifi_efuse_dst ]; then
cp $wifi_efuse_src $wifi_efuse_dst && echo "Wifi Map: cp $wifi_efuse_src $wifi_efuse_dst"
CHIPHD_NEED_REBUILD_SYS_IMG=true
fi
#### over-write build.prop
CHIPHD_OVERWRITE_BUILD_PROP_SH=$thisXwDevicePath/chiphd_overwrite_build_prop.sh
if [ -f "$CHIPHD_OVERWRITE_BUILD_PROP_SH" ]; then
old_buildprop_sha1sum=$(sha1sum $OUT/system/build.prop | awk '{print $1}')
bash $CHIPHD_OVERWRITE_BUILD_PROP_SH $OUT/system/build.prop
new_buildprop_sha1sum=$(sha1sum $OUT/system/build.prop | awk '{print $1}')
if [ "$old_buildprop_sha1sum" != "$new_buildprop_sha1sum" ]; then
CHIPHD_NEED_REBUILD_SYS_IMG=true
fi
fi
#### del apks
S_DelAPPSet=`echo Update.apk Home.apk YouTube.apk Chrome.apk Development.apk Gmail2.apk Hangouts.apk VideoEditor.apk Contacts.apk ChromeWithBrowser.apk OpenWnn.apk com.google.android.apps.maps_chiphd-0.apk Maps.apk`
if [ "$S_DelAPPSet" ]; then
for f in $S_DelAPPSet
do
S_DelAPP=$OUT/system/app/$f
if [ -f $S_DelAPP ]; then
rm $S_DelAPP && CHIPHD_NEED_REBUILD_SYS_IMG=true && echo "----del $S_DelAPP "
fi
S_DelAPP=$OUT/system/priv-app/$f
if [ -f $S_DelAPP ]; then
rm $S_DelAPP && CHIPHD_NEED_REBUILD_SYS_IMG=true && echo "----del $S_DelAPP "
fi
done
fi
#### rebuild system.img
if [ "$CHIPHD_NEED_REBUILD_SYS_IMG" = "true" ]; then
echo "------------- rebuild system.img"
make systemimage-nodeps
fi
#######################################################
#######################################################
cd $PACKAGE
chip=sun8iw5p1
platform=android
board=${thisXwBoard}
debug=uart0
sigmode=none
usage()
{
printf "Usage: pack [-cCHIP] [-pPLATFORM] [-bBOARD] [-d] [-s] [-h]
-c CHIP (default: $chip)
-p PLATFORM (default: $platform)
-b BOARD (default: $board)
-d pack firmware with debug info output to card0
-s pack firmware with signature
-h print this help message
"
}
while getopts "c:p:b:dsh" arg
do
case $arg in
c)
chip=$OPTARG
;;
p)
platform=$OPTARG
;;
b)
board=$OPTARG
;;
d)
debug=card0
;;
s)
sigmode=sig
;;
h)
usage
exit 0
;;
?)
exit 1
;;
esac
done
./pack -c $chip -p $platform -b $board -d $debug -s $sigmode
#### rename
if [ -f $XwImgRenameFunc ]; then
$XwImgRenameFunc --rename $thisCfgDir/$thisXwBoard/sys_config.fex $1
fi
另外一个脚本:
#!/bin/bash
# filename: cli-test.sh
UPCASE=false
DATE=""
usage() {
echo "USAGE:"
echo "cli-test <options>"
echo " -h : print help"
echo " -u : print info upcase"
echo " -p <xxx>: print info"
echo " -d <xxx>: date in print info"
}
print() {
if $UPCASE
then
echo -n $1 | tr a-z A-Z
else
echo -n $1
fi
if [ "$DATE" != "" ]
then
echo " date: $DATE"
else
echo ""
fi
}
while getopts "hup:d:" opt; do
case "$opt" in
h)
usage
exit 0
;;
u)
UPCASE=true
;;
d)
DATE=$OPTARG
;;
p)
print $OPTARG
;;
esac
done
运行规则:
自定义补全
上面的补全是补全固定的参数,简单,但是用处也不大,用户记不住的其实就是那些会变的参数内容。 下面尝试动态补全 cli-test.sh 的参数 -d 的内容(内容是当前日期以及前3天和后三天的日期) 修改 bash_complete 脚本如下:
_complete_func() {
local cur prev opts base
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
if [[ ${cur} == -* ]] ; then
opts="-h -u -d -p"
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
else
opts=$( _complete_d_option )
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
fi
return 0
}
_complete_d_option() {
date -v -3d +"%Y-%m-%d"
date -v -2d +"%Y-%m-%d"
date -v -1d +"%Y-%m-%d"
date +"%Y-%m-%d"
date -v +1d +"%Y-%m-%d"
date -v +2d +"%Y-%m-%d"
date -v +3d +"%Y-%m-%d"
}
complete -F _complete_func cli-test.sh
测试动态补全的效果
bash-3.2$ source bash_complete # 使自动补全脚本生效
bash-3.2$ ./cli-test.sh -u -d 2016-10-1<TAB><TAB> # 这是 2016-10-13 执行的结果,其他日子的结果会不一样
2016-10-10 2016-10-11 2016-10-12 2016-10-13 2016-10-14 2016-10-15 2016-10-16
上面就是动态补全,_complete_d_option 函数就是用来实现动态补全的。