前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SHELL 脚本随机题库

SHELL 脚本随机题库

原创
作者头像
大大刺猬
修改2021-03-19 10:20:47
1.1K0
修改2021-03-19 10:20:47
举报
文章被收录于专栏:大大刺猬

有时候不得不整题库, 但是题库是固定的,没得效果. 所以我弄了个脚本把题库随机下, 这样效果会好点.

本脚本比较特殊, 需要手动把题库放进脚本(感觉使用方便点, 不喜欢的可以改为加个命令cat就是了)

脚本见文末:

1. 题库格式:

目前支持 单选题, 多选题, 和判断题

需要在题目前加上题的类型+空格

选项只能是ABCDE这种字母+点+空格

需要给出正确答案,正确答案:+空格+正确答案

例子:

代码语言:javascript
复制
[单选题] 1 + 1 = ?
A. 1
B. 2
C. 3
D. 4
正确答案: B


[多选题] 以下哪些属于shell
A. bash
B. csh
C. zsh
D. ksh
正确答案: ABCD

[多选题] 以下哪些命令可以探听端口
A. echo
B. telnet
C. ssh
D. nmap
正确答案: ABCD

[判断题] PHP是世界上最好的语言
A. 对
B. 错
正确答案: B

2. 使用演示

使用方法很简单,直接执行 就可以了

代码语言:javascript
复制
sh randomQbyDdcw.sh
回答可以用字母,数字, 可以用逗号分号之类的隔开,也可以不隔开
回答可以用字母,数字, 可以用逗号分号之类的隔开,也可以不隔开
回答完了,会显示准确率, 和答题时间 和答题过程(放在文件里的,记录了哪些对了)
回答完了,会显示准确率, 和答题时间 和答题过程(放在文件里的,记录了哪些对了)

3. 彩蛋和其它

也不能叫彩蛋吧, 只是人性化了一丢丢

3.1 中途ctrl+c之后, 也会显示之前做的结果

3.2 执行脚本加上第一个位置参数,即可显示正确答案

主要是刚开始做的时候,不熟悉用.

还是挺人性化的
还是挺人性化的

3.3 思路讲解

把题干,选项,正确答案分别放在3个文件中,

生成一个随机数(范围是剩余题数之类的) 表示这是第N题.

然后打印题干.

去掉选项的A. B.之类的, 并在正确答案前加上关键词TRUE_FLAG_DDCW, 然后随机10次(默认的,可以改脚本),记录正确答案 并打印选项

获取用户的回答,格式化一下(换成有序的ABCD这种格式), 与正确答案比较, 对了就加个标识(正确了,666) ,然后下一题

最后统计正确数,和时间.

4. 具体的SHELL脚本

代码语言:javascript
复制
#!/bin/env bash
#write by ddcw at 2021.03.05
#支持ctrl+c

#changlog
#隐藏彩蛋: sh thisscript.sh ANY  就会默认输出正确答案

#因为用了read的缘故
stty erase ^H

#run this function and exit with $2
function exits(){
  echo -e "[`date +%Y%m%d-%H:%M:%S`] \033[31;40m$1\033[0m"
  [ -z $2 ] && exit $2
  exit 1
}

function echo_color() {
  case $1 in
    green)
      echo -e "\033[32;40m$2\033[0m"
      ;;
    red)
      echo -e "\033[31;40m$2\033[0m"
      ;;
    error|erro|ERROR|E|e)
      echo -e "[\033[1;5;41;33mERROR\033[0m `date +%Y%m%d-%H:%M:%S`] \033[1;41;33m$2\033[0m"
      ;;
    redflicker)
      echo -e "\033[1;5;41;33m$2\033[0m"
      ;;
    info|INFO|IF|I|i)
      echo -e "[\033[32;40mINFO\033[0m `date +%Y%m%d-%H:%M:%S`] \033[32;40m$2\033[0m"
      ;;
    highlightbold)
      echo -e "\033[1;41;33m$2\033[0m"
      ;;
    warn|w|W|WARN|warning)
      echo -e "[\033[31;40mWARNNING\033[0m `date +%Y%m%d-%H:%M:%S`] \033[31;40m$2\033[0m"
      ;;
    *)
      echo "INTERNAL ERROR: echo_color KEY VALUE"
      ;;
  esac
}

#上面都是客套话, 下面才是脚本正文
dt=$(date +%s) #起始时间
QANDA="/tmp/.${0}_${dt}_ddcw.question" #这个文件是放原题的
QFLAG1="/tmp/.${0}_${dt}_ddcw.seq1"   #这个是临时文件,是放题干的
QFLAG2="/tmp/.${0}_${dt}_ddcw.seq2"   #选项的
QFLAG3="/tmp/.${0}_${dt}_ddcw.seq3"   #答案的
SWITCH_TEMP="/tmp/.${0}_${dt}_ddcw.switch"  #选项排序的, 默认随机10次
SWITCH_TEMP_2="/tmp/.${0}_${dt}_ddcw.switch2" #排序后 加序号的, 默认ABCDEFG
RESULT_QA="/tmp/${0}_${dt}_ddcw.result"       #用户最终可以查看该文件回顾
cat /dev/null > ${RESULT_QA} #先重置下这个文件
cat << EOFLAG > ${QANDA}
[单选题] 1 + 1 = ?
A. 1
B. 2
C. 3
D. 4
正确答案: B


[多选题] 以下哪些属于shell
A. bash
B. csh
C. zsh
D. ksh
正确答案: ABCD

[多选题] 以下哪些命令可以探听端口
A. echo
B. telnet
C. ssh
D. nmap
正确答案: ABCD

[判断题] PHP是世界上最好的语言
A. 对
B. 错
正确答案: B


EOFLAG
grep -nE  '^\[单选题\] |^\[多选题\] |^\[判断题\] '  ${QANDA} | awk -F : '{print $1}' > ${QFLAG1}
grep -n  '^A. '  ${QANDA} | awk -F : '{print $1}' > ${QFLAG2}
grep -n  '^正确答案: '  ${QANDA} | awk -F : '{print $1}' > ${QFLAG3}
TOTAL_QUESTION=$(wc -l ${QFLAG1} | awk '{print $1}')
CURRENT_QUESTION=1


function PRINT_END(){
	END_TIME=$(date +%s)
	RIGHT_TOTAL=$(grep "(正确了,666)" ${RESULT_QA} | wc -l)
	echo_color info "准确率: ${RIGHT_TOTAL}/${TOTAL_QUESTION}"
	echo_color warn "you can visit ${RESULT_QA} to known more..."
	echo_color info "COST $[ (${END_TIME} - ${dt}) / 60 ] minitus"
QANDA="/tmp/.${0}_${dt}_ddcw.question" #这个文件是放原题的
QFLAG1="/tmp/.${0}_${dt}_ddcw.seq1"   #这个是临时文件,是放题干的
QFLAG2="/tmp/.${0}_${dt}_ddcw.seq2"   #选项的
QFLAG3="/tmp/.${0}_${dt}_ddcw.seq3"   #答案的
SWITCH_TEMP="/tmp/.${0}_${dt}_ddcw.switch"  #选项排序的, 默认随机10次
SWITCH_TEMP_2="/tmp/.${0}_${dt}_ddcw.switch2" #排序后 加序号的, 默认ABCDEFG
RESULT_QA="/tmp/${0}_${dt}_ddcw.result"       #用户最终可以查看该文件回顾
for file in ${QANDA} ${QFLAG1} ${QFLAG2} ${QFLAG3} ${SWITCH_TEMP} ${SWITCH_TEMP_2}
do
	[[ -f ${i} ]] && rm -rf ${i}
done

}
#异常判断的,如果用户ctrl+c了, 也能正常输出
trap 'WhenCtrlC' INT
function WhenCtrlC () {
PRINT_END
#彩蛋, 暂时不想写了
#if [[ ! -z ${1} ]] && [[ ${TOTAL_QUESTION} -gt $[ ${RIGHT_TOTAL} + 5 ] ]]; then
#echo_color err "跟着做都不能全对, 呵呵..."
#fi
exit 1
}

while [[ ${CURRENT_QUESTION} -le ${TOTAL_QUESTION} ]]
do
	rest_of=$[ ${TOTAL_QUESTION} - ${CURRENT_QUESTION} + 1 ]
	random_t=$[ ${RANDOM} % ${rest_of} + 1 ]
	seq1=$(sed -n "${random_t},1p" ${QFLAG1} )
	seq2=$(sed -n "${random_t},1p" ${QFLAG2} )
	seq3=$(sed -n "${random_t},1p" ${QFLAG3} )
	sed -i "${random_t},1d" ${QFLAG1} 
	sed -i "${random_t},1d" ${QFLAG2} 
	sed -i "${random_t},1d" ${QFLAG3} 
	seq1_1=$[ ${seq2} - 1 ]
	seq2_1=$[ ${seq3} - 1 ]
	clear
	for i in {1..40};do echo -n "#";done; echo -n "题目如下";for i in {1..40};do echo -n "#";done;echo "";

	#这是题目
	echo -n "[${CURRENT_QUESTION}/${TOTAL_QUESTION}] " | tee -a ${RESULT_QA}
	sed -n "${seq1},${seq1_1}p" ${QANDA} | tee -a ${RESULT_QA}

	for i in {1..40};do echo -n "#";done; echo -n "选项如下";for i in {1..40};do echo -n "#";done;echo "";
	echo ""
	sed -n "${seq2},${seq2_1}p" ${QANDA} > ${SWITCH_TEMP}
	sed -i '/^$/d' ${SWITCH_TEMP}  #排除空行
	SWITCH_TOTAL_NUMBER=$(wc -l ${SWITCH_TEMP} | awk '{print $1}') #每道题的选项总数
	sed -i "s/^[A-Z]. //" ${SWITCH_TEMP}  #把A. B. 这种去掉
	RIGHT_A=$(sed -n "${seq3},1p" ${QANDA} | awk '{print $NF}')
	#temp_seq 这是原来的正确答案序列
	temp_seq=$(eval eval echo {0..$[ $(echo ${RIGHT_A} | wc -c) - 2 ]})
	#给正确选项加个标识TRUE_FLAG_DDCW
	for j in ${temp_seq}
	do
		RIGHT_LINES=$(echo "${RIGHT_A:j:1}"| sed 's/A/1/g; s/B/2/g; s/C/3/g; s/D/4/g; s/E/5/g; s/F/6/g; s/G/7/g; s/H/8/g')
		temp_val_1="TRUE_FLAG_DDCW"$(sed -n "${RIGHT_LINES},1p" ${SWITCH_TEMP} )
		sed -i "${RIGHT_LINES},1c${temp_val_1}" ${SWITCH_TEMP}
	done

	#随机产生, 也就是给选项排个序, 默认是随机10次
	for r in {1..10}
	do
		switch_flag=$[ ${RANDOM} % ${SWITCH_TOTAL_NUMBER} + 1 ]
		switch_flag_val=$(sed -n "${switch_flag},1p" ${SWITCH_TEMP})
		sed -i "${switch_flag},1d" ${SWITCH_TEMP}
		echo ${switch_flag_val} >> ${SWITCH_TEMP}
	done

	#输出选项
	#sed 's/TRUE_FLAG_DDCW//' ${SWITCH_TEMP} | awk '{printf("%d. %s\n",NR,$0)}' | sed 's/^1\. /A. /; s/^2\. /B. /;   s/^3\. /C. /; s/^4\. /D. /; s/^5\. /E. /; s/^6\. /F. /; s/^7\. /G. /; s/^8\. /H. /; s/^9\. /I. /g;'
	awk '{printf("%d. %s\n",NR,$0)}' ${SWITCH_TEMP} | sed 's/^1\. /A. /; s/^2\. /B. /;   s/^3\. /C. /; s/^4\. /D. /; s/^5\. /E. /; s/^6\. /F. /; s/^7\. /G. /; s/^8\. /H. /; s/^9\. /I. /g;' > ${SWITCH_TEMP_2}
	sed 's/TRUE_FLAG_DDCW//' ${SWITCH_TEMP_2} | tee -a ${RESULT_QA}
	RIGHT_FLAG=$(grep TRUE_FLAG_DDCW ${SWITCH_TEMP_2} | awk -F . '{print $1}' | sort | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//')
	#sed 's/TRUE_FLAG_DDCW//' ${SWITCH_TEMP} 

	#获取用户的输入, 并格式化方便比较
	echo ""
	[[ -z ${1} ]] || echo "正确答案为: ${RIGHT_FLAG}" #彩蛋, 如果有任何位置参数, 就会输出正确答案
	read -p "我的答案: " USER_ANSWER
	USER_ANSWER=$(echo ${USER_ANSWER} | sed 's/1/A/g; s/2/B/g; s/3/C/g; s/4/D/g; s/5/E/g; s/6/F/g; s/7/G/g; s/8/H/g; s/9/I/g;')
	FORMAT_USER_ANSWER=$(echo ${USER_ANSWER} | awk -F '' '{for(i=N+1;i<=NF;i++)printf $i " " ;printf"\n"}' | sed 's/\,/\n/g; s/ /\n/g;   s/\;/\n/g;  s/\t/\n/g'| sed '/^$/d' | tr "[a-z]" "[A-Z]" | sort | uniq | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//' | sed 'N;s/\n//')

	#比对答案, 对了就加个标识 (正确了,666)
	echo "正确答案为: ${RIGHT_FLAG}" >> ${RESULT_QA}
	if [[ ${RIGHT_FLAG} == ${FORMAT_USER_ANSWER} ]];then
		echo "你的答案为: ${FORMAT_USER_ANSWER}(正确了,666)" >> ${RESULT_QA}
	else
		echo "你的答案为: ${FORMAT_USER_ANSWER}" >> ${RESULT_QA}
	fi
	echo "" >> ${RESULT_QA}
	echo "" >> ${RESULT_QA}

CURRENT_QUESTION=$[ ${CURRENT_QUESTION} + 1 ]
done

PRINT_END

想不到我竟然会写这种脚本 -_-

分享出来供学习学习吧

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 题库格式:
  • 2. 使用演示
  • 3. 彩蛋和其它
    • 3.1 中途ctrl+c之后, 也会显示之前做的结果
      • 3.2 执行脚本加上第一个位置参数,即可显示正确答案
        • 3.3 思路讲解
        • 4. 具体的SHELL脚本
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档