shell下听写单词脚本(改进版)

sh/bash/dash/ksh/zsh等Shell脚本
回复
fnan
帖子: 919
注册时间: 2009-07-01 22:04
送出感谢: 0
接收感谢: 13 次

shell下听写单词脚本(改进版)

#1

帖子 fnan » 2011-03-30 13:32

stardict可以收藏单词到dic.txt文件,利用这个文件和wave发音文件,写了个英语单词听写脚本,主要是练习略微复杂一点的写法,选项多细节也增多。
修正一些bug, 增加功能:

代码: 全选

#!/bin/bash

#begin
#{
	export env_file_fifo="fifo$$"
	export env_word_file
	export env_pts=$(tty)
				vg_echo="\n -f 单词文本\n 设定单词文本。\n\n
				-d wav文件地址\n 设定wav文件夹地址。\n\n
				-r\n 删除配置文件。\n\n
				-h\n 帮助。\n\n
				【【在听写模式下直接输入:】】\n\n
				数字-数字(x-y)\n听写第x组到第y组。\n\n
				g数字 (gx)\n每组x个单词。\n\n
				s数字 (sx)\n从第x组开始听写。\n\n
				00 \n配置写入磁盘并退出。\n\n
				ENTER\n单击输入键重复发音。\n\n
				e数字 (ex)\n错x次显示单词。\n\n
				-cs\n查询词义『然后关闭或最小化stardict窗口,可按ALT+F4 或ALT+F9』\n\n
				-drw\n删除当前单词文本中重复单词合为一个。\n\n
				-utl\n把当前文本的大写字母改为小写字母。\n\n
				-dwww\n删除当前文本中没有wave文件的单词,注意必须先在听写模式下出现过的词才能删除!\n\n
				-h\n帮助\n\n"
	vg_configuration_file=$0
	vg_configuration_file=".${vg_configuration_file#./}.confg"
	if [[ $# -eq 0 && ! -f ~/$vg_configuration_file ]];then
		echo
		echo "请先输入选项: $0 -f 单词文本 -d wav文件夹地址 [-h 『帮助』] "
		echo
		exit 1
	fi	
	if [[ $# -ne 0 ]];then
		while getopts ":f:d:rh" optname
		do
			case "$optname" in
				"h")
				echo -e $vg_echo|more
				echo
				exit 0
				;;
				"f")
				env_word_file=$OPTARG
				echo "单词文本=$env_word_file"
				;;
				"d")
				vg_wave_directory=$OPTARG
				echo "wav文件地址=$vg_wave_directory"
				;;
				"r")
				echo "删除配置文件?y/n"
				read -n1 vg_read
				if [[ $vg_read = "y" ]];then
					echo
					if [[ -f ~/$vg_configuration_file ]];then
						rm ~/$vg_configuration_file && echo "已删除$vg_configuration_file配置文件。"
					else
						echo "无配置文件。"
					fi
					exit 0
				fi
				;;
				"?")
				echo "未知选项? "$OPTARG
				exit 1
				;;
				":")
				echo "选项 "$OPTARG" 缺参数!"
				exit 1
				;;
				"*")
				echo "发生未知错误!"
				exit 1
				;;
			esac
		done
	fi
	if [[ ! -f ~/$vg_configuration_file ]];then
		if [[ -z $vg_wave_directory ]];then
			echo "缺wave文件夹参数!"
			exit 1
		fi
		if [[ -z $env_word_file ]];then
			echo "缺单词文本参数!"
			exit 1
		fi
	else
		if [[ -z $env_word_file ]];then 
			env_word_file=`sed '1q;d' ~/$vg_configuration_file`
		fi
		if [[ -z $vg_wave_directory ]];then 
			vg_wave_directory=`sed '2q;d' ~/$vg_configuration_file`
		fi
	fi
	if [[ ! -f $env_word_file ]];then
		echo "单词文本不存在!"
		exit 1
	elif (! head $env_word_file|grep -q '[a-zA-Z]');then
		echo "单词文本为空!"
		exit 1   
	elif [[ ! -d $vg_wave_directory ]];then
		echo "wave文件夹不存在!"
		exit 1
	fi
#}
function f_delete_repeat_word
{
	awk '{print $1 " " NR|"sort -k1,1"}' $env_word_file|awk 'BEGIN{n = 0} 
		{if (vl_2 == $1) {n++;a[n] = $2}; vl_2 = $1}
		END{if (n != 0) 
		    	{print "\n检察出" n "个重复词."|"cat > $env_pts"}
	            else
		    	{print "\n没有重复词。"|"cat > $env_pts";exit 1};
		    n2 = 0;
		    while (getline vl_l < ENVIRON[ "env_word_file" ]) 
		    	{
			n2++
			for (i in a)
				{
				o = "p"
				if (a[i] == n2)
					{
					o = "np"
					break
					};
				};
			if (o == "p")
				print vl_l;
			}
	           }' > "tmp$$"
	if [[ $? -eq 0 ]];then
		mv "tmp$$" $env_word_file
		echo -e "\033[7m已写入$env_word_file文本.\033[0m"
	else
                rm "tmp$$"   #已加上缺少的指令。
		return 1
	fi
}
function f_delete_without_wave_file_word
{
	echo $vg_wwf_word|awk  '{vl_wn = split($0,al_w," ")} 
            END{print "将删除" vl_wn "个无wave文件的单词。"|"cat > $env_pts"; n = 0; while (getline vl_l < ENVIRON[ "env_word_file" ])
		               {
        	               n++
                	       o = "p"
			       for (i in al_w)
			       		{
				        if (vl_l == al_w[i])
                              		{		
	                                        delete al_w[i];
        	                                o = "np";
                         		        break
                               		 };
                               };
                      	       if (o == "p")
                      			{		
	  	                        print vl_l
                		        };
		               }		
               }' > "tmp$$"
	       if [[ $? -eq 0 ]];then
			mv "tmp$$" $env_word_file
	       		echo -e "\033[7m已在$env_word_file文本中删除单词。\033[0m"
		else
			return 1
 	       fi
}
function f_get_without_wave_file_word
{
	vg_wwf_word="$vg_wwf_word $1"
	vg_wwf_word=$(echo $vg_wwf_word|xargs -n1|sort -u|xargs)
}
function f_get_group_count_and_word_number
{
	if [[ ! -f ~/$vg_configuration_file ]];then
		vg_group_word_number=100
	else
		vg_group_word_number=$(sed '3q;d' ~/$vg_configuration_file)
	fi
	if [[ $vg_group_word_number -gt $vg_file_word_number || -z $vg_group_word_number ]];then
		vg_group_word_number=$vg_file_word_number
	fi
	vg_group_count=$(($vg_file_word_number/$vg_group_word_number))
	if [[ $(($vg_file_word_number%$vg_group_word_number)) -ne 0 ]];then
		((vg_group_count++))
	fi
}
function f_get_group_range
{
	f_get_group_count_and_word_number
	if [[ -f ~/$vg_configuration_file ]];then
		vg_first_group=`sed '4q;d' ~/$vg_configuration_file`
		vg_last_group=`sed '5q;d' ~/$vg_configuration_file`
		vg_group_sequence=`sed '6q;d' ~/$vg_configuration_file`
		vg_error_number=`sed '7q;d' ~/$vg_configuration_file`
	else
		vg_first_group=1
		vg_last_group=$vg_group_count
		vg_group_sequence=1
		vg_error_number=3
	fi
}
function f_make_configure_file
{
		echo "$env_word_file" > ~/$vg_configuration_file
		echo "$vg_wave_directory" >> ~/$vg_configuration_file
		echo "$vg_group_word_number" >> ~/$vg_configuration_file
		echo "$vg_first_group" >> ~/$vg_configuration_file
		echo "$vg_last_group" >> ~/$vg_configuration_file
		echo "$vg_group_sequence" >> ~/$vg_configuration_file
		echo "$vg_error_number" >> ~/$vg_configuration_file
}
function f_check_groups
{
	if [[ $vg_first_group -gt $vg_group_count ]];then
		vg_first_group=$vg_group_count
	
	fi
	if [[ -z $vg_first_group ]];then
		vg_first_group=1
	fi
	if [[ $vg_last_group -gt $vg_group_count ]];then
		vg_last_group=$vg_group_count
	fi
	if [[ -z $vg_last_group ]];then
		vg_last_group=$vg_group_count
	fi
	if [[ $vg_group_sequence -gt $vg_last_group ]];then
		vg_group_sequence=$vg_last_group
	fi
	if [[ -z $vg_group_sequence || $vg_group_sequence -le 0 ]];then
		vg_group_sequence=1
	fi
	if [[ $vg_group_sequence -lt $vg_first_group ]];then
		vg_group_sequence=$vg_first_group
	fi
	if [[ -z $vg_error_number || $vg_error_number -le 0 ]];then
		vg_error_number=1
	fi
	f_make_configure_file
}
function f_get_configure
{
	vg_file_word_number=`wc -w < $env_word_file`
	f_get_group_range
	f_check_groups
	echo '共有'${vg_file_word_number}'个单词,每组'${vg_group_word_number}'个,共'${vg_group_count}'组,练习'${vg_first_group}'-'${vg_last_group}'组,第'${vg_group_sequence}'组开始,错'$vg_error_number'次显示单词。'
}
function f_get_group_words
{
	local vl_command
	local vl_first_word
	local vl_last_word
	declare -i vl_l
	local vl_n
	local vl_w
	declare -i vl_r
	if [[ $vg_group_count -eq 1 ]];then
		vl_command='1,$p'
	else
		vl_first_word=$((($vg_group_sequence-1)*$vg_group_word_number+1))
		if [[ $(($vg_group_sequence*$vg_group_word_number)) -ge $vg_file_word_number ]];then
			vl_last_word='$'
		else
			vl_last_word=$(($vg_group_sequence*$vg_group_word_number))
		fi
		vl_command=$vl_first_word','$vl_last_word'p'
	fi
	ag_words=($(sed -n $vl_command ~/$env_word_file))
	vl_l=${#ag_words[@]}
	vl_n=0
	while [[ $vl_n -lt $vl_l ]];do
		vl_r=$((($RANDOM$(date +%N))%$vl_l))
		vl_w=${ag_words[$vl_n]}
		ag_words[vl_n]=${ag_words[$vl_r]}
		ag_words[vl_r]=$vl_w
		((vl_n++))
	done
}
function f_consult_word
{	
	stardict ${ag_words[vl_n]} &>/dev/null&
	local vl_pid=$(echo $! )
	while read vl_order < $env_file_fifo;do
		if [[ $vl_order == "quit" ]];then
			kill $vl_pid&
			break
		fi
	done
	rm $env_file_fifo
	aplay -q $vl_w&
}
function f_MAIN
{
	f_get_configure
	vg_read=1
	local vl_n2
	local vl_n3
	local vl_w
	local vl_l
	vg_read=
	((vg_group_sequence--))
	while [[ $vg_read != "00" ]];do	
		((vg_group_sequence++))
		if [[ $vg_group_sequence -gt $vg_last_group ]];then
			vg_group_sequence=$(($vg_first_group))
		fi
		f_get_group_words
		echo "第$vg_group_sequence 组"
		vl_n=0
		vl_n3=0
		while [[ $vl_n -le $((${#ag_words[@]} - 1)) ]];do
			vg_read=
			vl_w=${ag_words[vl_n]}
			vl_w=$vg_wave_directory${vl_w:0:1}'/'${vl_w}'.wav'
			if [[ -f $vl_w ]];then
				aplay -q $vl_w&	
				vl_n3=0
			else
				echo "-无${ag_words[vl_n]}的wave文件。"
				f_get_without_wave_file_word ${ag_words[vl_n]}
				((vl_n++))
				((vl_n3++))
				if [[ $vl_n -eq ${#ag_words[@]} ]];then
					vl_n=0
					if [[ $vl_n3 -eq ${#ag_words[@]} ]];then
						vl_n3=0
						echo -e "\033[31m整组单词无wave文件,启动自动删除!\033[0m"
						f_delete_without_wave_file_word
						if [[ $? -eq 0 ]];then
							f_check_groups
							vg_repeat_main="y"
							return
						else
							exit 1
						fi
					fi
				fi
				continue
			fi
			vl_n2=0
			while [[ $vg_read != ${ag_words[vl_n]} ]];do
				echo -n "单词$(($vl_n+1))》 "
				read vg_read
				if (grep -q '[0-9]-[0-9]' <<<$vg_read);then
					vg_first_group=${vg_read%%-*}
					vg_last_group=${vg_read##*-}
					f_check_groups
					vg_repeat_main="y"
					return
				elif [[ $vg_read = "00" ]];then
					f_make_configure_file
					exit 0
				elif [[ -z $vg_read ]];then
					aplay -q $vl_w&
				elif (grep -E -q 'g[0-9]+' <<<$vg_read);then
					vg_group_word_number=${vg_read##*g}
					if [[ $vg_group_word_number -gt $vg_file_word_number ]];then
						vg_group_word_number=$vg_file_word_number
					elif [[ $vg_group_word_number -le 0 ]];then
						vg_group_word_number=1
					fi
						f_make_configure_file
						vg_repeat_main="y"
						return
				elif (grep -E -q 's[0-9]+' <<<$vg_read);then
					vg_group_sequence=${vg_read##*s}
					f_check_groups
					vg_repeat_main="y"
					return
				elif (grep -E -q 'e[0-9]+' <<<$vg_read);then
					vg_error_number=${vg_read##*e}
					f_check_groups
					vg_repeat_main="y"
					return
				elif (grep -qe '-cs' <<<$vg_read);then
					mkfifo $env_file_fifo
					f_consult_word&
					read -p "按ENTER键继续:"
					echo "quit" > $env_file_fifo
				elif (grep -qe '-drw' <<<$vg_read);then
					f_delete_repeat_word
					if [[ $? -eq 0 ]];then
						f_check_groups
						vg_repeat_main="y"
						return
					fi
				elif (grep -qe '-utl' <<<$vg_read);then
					sed -i 'y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' $env_word_file
					echo -e "\033[7m$env_word_file文本的大写字母已改为小写字母。\033[0m"
					vg_repeat_main="y"
					return
				elif (grep -qe '-dwww' <<<$vg_read);then
					if [[ ! -z $vg_wwf_word ]];then
						f_delete_without_wave_file_word
						if [[ $? -eq 0 ]];then
							f_check_groups
							vg_repeat_main="y"
							return
						else
							exit 1
						fi
					else
						echo "未出现无wave文件的单词!"
					fi
				elif (grep -qe '-h' <<<$vg_read );then
					clear
					echo -e $vg_echo|more
				elif [[ $vg_read != ${ag_words[vl_n]} ]];then
					vl_l=${#vg_read}
					((vl_n2++))
					aplay -q $vl_w&
					if [[ $vl_n2 -eq $vg_error_number ]];then
						echo -e "\033[33;47m${ag_words[vl_n]}\033[0m"
						vl_n2=0
					else
						for ((i=0;i<=$vl_l;i++));do
							if [[ ${vg_read:$i:1} = ${ag_words[vl_n]:$i:1} ]];then
								echo -n ${vg_read:$i:1}
							else
								echo -ne "\033[31m${vg_read:$i:1}\033[0m"
							fi
						done
					fi
					echo
				fi
					
				
			done	
				((vl_n++))
		done
	done
}
f_MAIN
while [[ $vg_repeat_main = "y" ]];do
	f_MAIN
done
exit 0
上次由 fnan 在 2011-04-05 22:51,总共编辑 2 次。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙
送出感谢: 4 次
接收感谢: 256 次

Re: shell下听写单词脚本

#2

帖子 eexpress » 2011-03-30 13:35

只看到lz的bash还不错。
其他看不出。没空。
● 鸣学
fnan
帖子: 919
注册时间: 2009-07-01 22:04
送出感谢: 0
接收感谢: 13 次

Re: shell下听写单词脚本(改进版)

#3

帖子 fnan » 2011-04-05 22:52

function f_delete_repeat_word #这个函数缺了一条有关临时文件的指令!****************************************
{
awk '{print $1 " " NR|"sort -k1,1"}' $env_word_file|awk 'BEGIN{n = 0}
{if (vl_2 == $1) {n++;a[n] = $2}; vl_2 = $1}
END{if (n != 0)
{print "\n检察出" n "个重复词."|"cat > $env_pts"}
else
{print "\n没有重复词。"|"cat > $env_pts";exit 1};
n2 = 0;
while (getline vl_l < ENVIRON[ "env_word_file" ])
{
n2++
for (i in a)
{
o = "p"
if (a == n2)
{
o = "np"
break
};
};
if (o == "p")
print vl_l;
}
}' > "tmp$$"
if [[ $? -eq 0 ]];then
mv "tmp$$" $env_word_file
echo -e "\033[7m已写入$env_word_file文本.\033[0m"
else
rm "tmp$$" #加上这一句,以免留下临时文件!*****************************************************************
return 1
fi
}
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
fnan
帖子: 919
注册时间: 2009-07-01 22:04
送出感谢: 0
接收感谢: 13 次

Re: shell下听写单词脚本(改进版)

#4

帖子 fnan » 2011-05-11 15:57

最近在原星际wave文件中加入了牛津的美式女声,由于格式问题aplay指令不能用了,作了一点改变:
aplay -q $vl_w& 改为 mplayer $vl_w &>/dev/null&
一共四句要改。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
tusooa
帖子: 6546
注册时间: 2008-10-31 22:12
系统: 践兔
送出感谢: 6 次
接收感谢: 10 次
联系:

Re: shell下听写单词脚本(改进版)

#5

帖子 tusooa » 2011-06-24 14:44

espeak xxx

代码: 全选

] ls -ld //
fnan
帖子: 919
注册时间: 2009-07-01 22:04
送出感谢: 0
接收感谢: 13 次

Re: shell下听写单词脚本(改进版)

#6

帖子 fnan » 2011-06-25 5:03

真人语音,不是机器语音。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
sdzhsh
帖子: 3
注册时间: 2011-06-27 18:06
送出感谢: 0
接收感谢: 0

Re: shell下听写单词脚本(改进版)

#7

帖子 sdzhsh » 2011-07-12 18:42

楼主强大! :em11 :em11
头像
yjcong
帖子: 2470
注册时间: 2006-02-28 3:11
送出感谢: 0
接收感谢: 0

Re: shell下听写单词脚本(改进版)

#8

帖子 yjcong » 2011-07-12 19:51

等待神的perl版
一梦三年,
松风依旧,
萝月何曾老.


灵幽听微, 谁观玉颜?
灼灼春华, 绿叶含丹.
回复

回到 “Shell脚本”