前言
最近在看NDN的代码,把一些常用的功能写成了脚本。突然在想能不能做成交互式的脚本呢?于是百度了下,发现 whiptail
支持这个,并且 Ubuntu
自带这玩意,并且在百度上找到了参考链接——交互式shell脚本对话框----whiptail指令。于是,准备开工。
主脚本Interactive.sh
代码如下——
#!/bin/bash
# 将上次执行结果$?作为参数传入,如果为不为0,则退出该shell
determine_whether_exit(){
if [ $1 != 0 ]; then
echo "您选择了退出Interactive.sh"
exit 1
fi
}
# 选择框(仅可选一个)
OPTION=$(whiptail --title "选择要执行的脚本" --menu "脚本列表" 24 80 15 \
"StringGrep.sh" "在区域内搜索指定字符串" \
"ExecuteNDN.sh" "执行NDN程序" \
"Interactive.sh" "重新进入自己" 3>&1 1>&2 2>&3)
determine_whether_exit $? # 如果选择了Esc,就退出shell
#cat ./$OPTION
#echo ""
./${OPTION}
该脚本用于控制选择选项
- StringGrep.sh
- ExecuteNDN.sh
- Interactive.sh(自己)
界面如下——
搜索包含指定字符串的文件StringGrep.sh
在 Interactive.sh
选择第一项按下回车,进入 StringGrep.sh
。该代码让用户输入搜索路径和待搜索的字符串(可以设置默认路径和默认字符串),查找返回对应的文件。用户可选择找到的文件用 VScode
打开。
代码如下——
#!/bin/sh
# 将上次执行结果$?作为参数传入,如果为不为0,则退出该shell
determine_whether_exit(){
if [ $1 != 0 ]; then
echo "您选择了退出StringGrep.sh"
exit 1
fi
}
# 默认查找的文件夹
default_file=~/NLSRndnSIM/ns-3/src
# 默认查找的字符串
default_str="NS3_NLSR_SIM"
# 交互式1:输入查找的文件夹file_name
file_name=$(whiptail --title "默认字符串为${default_str}" \
--inputbox "输入要cd到的目录" \
24 80 `# <height> <width>` \
${default_file} `# <default-text>` \
3>&1 1>&2 2>&3)
determine_whether_exit $? # 如果选择了Esc,就退出shell
# 当然,这一步并不必要
cd ${file_name}
# 交互式2:输入被查找的str
str_name=$(whiptail --title "查找目录${file_name}" \
--inputbox "输入要查找的字符串" \
24 80 `# <height> <width>` \
${default_str} `# <default-text>` \
3>&1 1>&2 2>&3)
determine_whether_exit $? # 如果选择了Esc,就退出shell
# 显示当前搜索信息
echo "当前目录:${file_name}"
echo "字符串:\"${str_name}\"搜索ing..."
# 查找字符串,返回查找结果
grep -rl ${str_name} ${file_name} # 显示查找结果到终端
find_str=$(grep -rl ${str_name} ${file_name}) # 储存查找结果
# 根据找到的文件生成多选框,用户可选择想用VScode打开的文件
choose_open=""
open_file="choose_open=\$(whiptail --title 查找目录\${file_name}\
--checklist 查找字符串\${str_name} 24 80 15"
for element in ${find_str}; do
open_file="${open_file} ${element} + OFF"
done
open_file="${open_file} 3>&1 1>&2 2>&3)"
# 交互式3:打开用户选择打开的文件
eval ${open_file}
determine_whether_exit $? # 如果选择了Esc,就退出shell
for element in ${choose_open}; do
element=${element#\"} # 删掉头部的"
element=${element%\"} # 删掉尾部的"
code $element # 用VScode打开用户的结果
done
cd ~/Desktop/MyShell/
首先是输入文件路径,这里显示的是默认路径,回车代表确定
然后是输入查找的字符串,这里显示的是默认字符串,回车代表确定
最后是回显查找到的目标文件名,通过空格选择,按下回车确定用 VScode
打开——
退出后在命令行里会保留显示查找到的文件名——
ExecuteNDN.sh
具体功能懒得介绍了。代码如下——
#!/bin/bash
# 将上次执行结果$?作为参数传入,如果为不为0,则退出该shell
determine_whether_exit(){
if [ $1 != 0 ]; then
echo "您选择了退出ExecuteNDN.sh"
exit 1
fi
}
cd ~/NLSRndnSIM/ns-3/ # ndnSIM的路径
default_file=ndn-nlsr-simple # 默认执行内容
# 交互式1:多选框选择NS_LOG输出项目
DISTROS=$(whiptail --title "选择NS_LOG输出的项目" --checklist \
"空格选中对应项,回车确认所有项" 24 80 15 \
"ndn-cxx.ndn.Face" "" OFF \
"ndn.App" "" OFF \
"ndn.Consumer" "" OFF \
"ndn.Producer" "" OFF \
"nlsr" "" OFF \
"nlsr.ConfFileProcessor" "" OFF \
"nlsr.ConfParameter" "" OFF \
"nlsr.adjacent" "" OFF \
"nlsr.fib" "" OFF \
"ndn-cxx.nfd.ContentStore" "" OFF \
"ndn-cxx.nfd.CsPolicy" "" OFF \
"ndn-cxx.nfd.FaceTable" "" OFF \
"ndn-cxx.nfd.FibManager" "" OFF \
"ndn-cxx.nfd.Forwarder" "" OFF \
"ndn-cxx.nfd.GenericLinkService" "" OFF \
"ndn-cxx.nfd.LinkService" "" OFF \
"ndn-cxx.nfd.MulticastStrategy" "" OFF \
"ndn-cxx.nfd.NameTree" "" OFF \
"ndn-cxx.nfd.Rib" "" OFF \
"ndn-cxx.nfd.RibEntry" "" OFF \
"ndn-cxx.nfd.RibManager" "" OFF \
"ndn-cxx.nfd.RibService" "" OFF \
"ndn-cxx.nfd.Strategy" "" OFF \
"ndn-cxx.nfd.Transport" "" OFF \
"ndn.AppHelper" "" OFF \
"ndn.AppLinkService" "" OFF \
"ndn.FibHelper" "" OFF \
"ndn.GlobalRoutingHelper" "" OFF \
"ndn.GlobalRoutingHelperLfid" "" OFF \
"ndn.NetDeviceTransport" "" OFF \
"ndn.StrategyChoiceHelper" "" OFF 3>&1 1>&2 2>&3)
determine_whether_exit $? # 如果选择了Esc,就退出shell
# 解析多选框的结果
exec_str=""
read_flag=0 # 第一个字符拼接时不加冒号,后面的要加
for element in ${DISTROS[*]}; do
element=${element//\"/} # 去掉字符串的双引号
if [ $read_flag = 0 ]; then # 第一个加前缀NS_LOG=
exec_str="NS_LOG=${element}"
read_flag=1
else # 后面的用:隔开
exec_str="${exec_str}:${element}"
fi
done
# 交互式2:输入file_name
file_name=$(whiptail --title "输入要执行的NDN文件" \
--inputbox "输入要执行的NDN文件" \
24 80 `# <height> <width>` \
${default_file} `# <default-text>` \
3>&1 1>&2 2>&3)
determine_whether_exit $? # 如果选择了Esc,就退出shell
# 添加待执行的file_name
if [ ${read_flag} = 1 ]; then
exec_str="${exec_str} ./waf --run=${file_name}"
else # 如果没有选择NS_LOG参数,就不加
exec_str="./waf --run=${file_name}"
fi
# 交互式3:是否加入--vis可视化参数
whiptail --title "是否采用--vis可视化显示" \
--yes-button "开启--vis参数" --no-button "不开启--vis参数"\
--yesno "是否采用--vis可视化显示" 24 80
exitstatus=$?
if [ $exitstatus = 0 ]; then # 如果是Yes
exec_str="${exec_str} --vis"
elif [ $exitstatus = 1 ]; then # 如果是No
exec_str=${exec_str}
else # 如果选择了Esc,就退出shell
determine_whether_exit $exitstatus
fi
# 显示执行的命令,并最终执行
echo "执行${exec_str}"
eval ${exec_str}
cd ~/Desktop/MyShell/
第一部分是选择要 NS_LOG
日志显示的参数,这里选择了 ndn.Consumer
和 ndn.Producer
——
然后选择要执行的文件,这里选择了默认的 ndn-nlsr-simple
——
选择是否开启 --vis
参数,这里选择了否
最后根据我们的选项 ndn.Consumer
和 ndn.Producer
,文件为 ndn-nlsr-simple
,不开启 --vis
参数,得到了命令行参数
NS_LOG=ndn.Consumer:ndn.Producer ./waf --run=ndn-nlsr-simple
To be continued…
其他功能等想好了再往上加