免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2696 | 回复: 7
打印 上一主题 下一主题

一个简单的shell应用程序,求教各位大侠 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-03-02 18:22 |只看该作者 |倒序浏览
  1. #! /bin/sh
  2. ####fileName:cdManage.sh
  3. ####简单的唱片数据库管理程序
  4. ####专辑资料和专辑曲目资料分开存放在两个文件中
  5. #### $title_file是专辑资料文件,每行包括"专辑id,专辑名称,专辑类型,艺术家"(eg:CDL1,Oasis Owns the Oasis,Rock,Oasis)
  6. #### $tracks_file是专辑曲目资料文件,每行包括"专辑id,专辑曲目编号,曲目名称"(eg:CDL1,1,Little by Little)
  7. #### 出自图灵出版社<<Linux程序设计>> P67 - P76

  8. menu_choice="";
  9. current_cd="";
  10. title_file="title.cdb";
  11. tracks_file="track.cdb";
  12. temp_file=/tmp/cdb.$$;
  13. trap 'rm -f $temp_file' EXIT;
  14. get_return()
  15. {
  16.    echo -e "Press return \c";
  17.    read x
  18.    return 0;
  19. }


  20. get_confirm()
  21. {
  22.     echo -e "Are you sure? \c";
  23.     while true
  24.     do
  25.        read x
  26.        case "$x" in
  27.          y | yes | Y | Yes | YES )
  28.            return 0;;
  29.          n | no | N | No | NO )
  30.            echo;
  31.            echo "Cancelled"
  32.            return 1;;
  33.          *) echo "Please enter yes or no" ;;
  34.        esac
  35.     done
  36. }

  37. set_menu_choice()
  38. {
  39.     clear;
  40.     echo "Options:-";
  41.     echo
  42.     echo "    a) Add new CD"
  43.     echo "    f) Print CD"
  44.     echo "    c) Count the CDs and tracks in the catalog"
  45.     if  [ "$cdcatnum" != "" ];then
  46.     echo "    l) List tracks on $cdtitle";
  47.     echo "    r) Remove $cdtitle";
  48.     echo "    u) Update track infomation for $cdtitle";
  49.     fi
  50.     echo "    q) Quit"
  51.     echo
  52.     echo -e "Please enter choice then press  return \c";
  53.     read menu_choice;
  54.     return;
  55. }

  56. insert_title()
  57. {
  58.   echo $*  >> $title_file
  59.   return
  60. }

  61. insert_track()
  62. {
  63.   echo $* >> $tracks_file
  64.   return;
  65. }

  66. add_record_tracks()
  67. {
  68.    echo "Enter track information for this CD";
  69.    echo "When no more tracks enter q";
  70.    cdtrack=1;
  71.    cdttitle="";
  72.    while [ "$cdttitle" != "q" ]
  73.    do
  74.      echo -e "Track $cdtrack, track title? \c"
  75.      read tmp
  76.      cdttitle=${tmp%%,*};
  77.      if [ "$tmp" != "$cdttitle" ];
  78.      then
  79.         echo "Sorry,no commas allowed"
  80.         continue
  81.      fi
  82.      if [ -n "$cdttitle" ];then
  83.        if [ "$cdttitle" != "q" ];then
  84.         insert_track  $cdcatnum,$cdtrack,$cdttitle;
  85.        fi
  86.      else
  87.         cdtrack=$((cdtrack-1));
  88.      fi
  89.      cdtrack=$((cdtrack+1));
  90.     done
  91. }

  92. add_records()
  93. {
  94.    echo -e "Enter catalog name \c";
  95.    read tmp
  96.    cdcatnum=${tmp%%,*};
  97.    
  98.    echo -e "Enter title \c";
  99.    read tmp
  100.    cdtitle=${tmp%%,*};

  101.    echo -e "Enter type \c";
  102.    read tmp
  103.    cdtype=${tmp%%,*}

  104.    echo -e "Enter composer/artists \c";
  105.    read tmp;
  106.    cdac=${tmp%%,*};

  107.    echo "About  to add new entry";
  108.    echo "$cdcatnum,$cdtitle,$cdtype,$cdac";
  109.    
  110.    if get_confirm;
  111.     then
  112.       insert_title $cdcatnum,$cdtitle,$cdtype,$cdac;
  113.       add_record_tracks;
  114.     else
  115.       remove_records;
  116.     fi
  117.   return;  
  118. }

  119.   find_cd()
  120. {
  121.     if [ "$1" = "n" ];then
  122.       asklist=n;
  123.     else
  124.       asklist=y
  125.     fi
  126.    
  127.     cdcatnum="";
  128.     echo -e "Enter a string to search for in the cd titles \c";
  129.     read searchstr
  130.     if [ "$searchstr" = "" ];then
  131.        return 0;
  132.     fi

  133.     grep "$searchstr" $title_file > $temp_file

  134.     set $(wc -l $temp_file);
  135.     linesfound=$1;
  136.    
  137.     case "$linesfound" in
  138.     0)     echo "Sorry,nothing found";
  139.            get_return;
  140.            return 0;;
  141.     1)     ;;
  142.     2)     echo "Sorry,not uniq";
  143.            echo "Found the following";
  144.            cat $temp_file;
  145.            get_return;
  146.            return 0;
  147.            ;;
  148.     esac

  149.     IFS=",";
  150.     read cdcatnum cdtitle cdtype cdac < $temp_file
  151.     IFS=" ";
  152.     if [ -z "$cdcatnum" ]; then
  153.        echo "Sorry, could not extract catalog field from $temp_file";
  154.        get_return;
  155.        return 0;
  156.     fi


  157.     echo
  158.     echo Catalog number: $cdcatnum;
  159.     echo Title: $cdtitle;
  160.     echo Type : $cdtype;
  161.     echo Artist/Composer : $cdac;
  162.     echo ;
  163.     get_return;
  164.      
  165.     if [ "$asklist" = "y" ]; then
  166.        echo -e "View tracks for this CD?  \c ";
  167.        read x;
  168.        if [ "$x" = "y" ]; then
  169.            echo
  170.            list_tracks;
  171.            echo
  172.        fi
  173.     fi
  174.     return 1;
  175.   }

  176.    update_cd()
  177.   {
  178.      if [ -z "$cdcatnum" ] ; then
  179.         echo "You must select a CD first"
  180.         find_cd n;
  181.      fi
  182.      if [ -n "$cdcatnum" ] ;then
  183.         echo "Current tracks are: -";
  184.         list_tracks;
  185.         echo
  186.         echo "This will re-enter the tracks for $cdtitle";
  187.         get_confirm && {
  188.           grep -v "^${cdcatnum}," $track_file > $tempfile;
  189.           mv $temp_file $tracks_file;
  190.           echo
  191.           add_record_tracks;
  192.           }
  193.        fi
  194.        return;
  195. }


  196. count_cds()
  197. {
  198.     set $(wc -l $title_file)
  199.     num_titles=$1;
  200.     set $(wc -l $tracks_file)
  201.     num_tracks=$1
  202.     echo "found $num_titles  CDs,with a total number of $num_tracks tracks";
  203.     get_return;
  204.     return;
  205. }

  206. remove_records()
  207. {
  208.     if [ -z "$cdcatnum" ];then
  209.        echo You must select a CD first
  210.        find_cd n
  211.     fi
  212.    
  213.     if [ -n "$cdcatnum" ] ;then
  214.        echo "You are about to delete $cdtitle"
  215.        get_confirm && {
  216.          grep -v "^${cdcatnum}," $title_file > $temp_file;
  217.          mv $temp_file $title_file
  218.          grep -v "${cdcatnum}," $tracks_file > $temp_file;
  219.          mv $temp_file $tracks_file
  220.          cdcatnum="";
  221.          echo Entry removed   
  222.         }
  223.       get_return;
  224.     fi
  225.       return;
  226. }

  227.     list_tracks()
  228. {
  229.      if [ "$cdcatnum" = "" ];then
  230.         echo "no CD selected yet \c"
  231.         return;
  232.      else
  233.         grep "^${cdcatnum}," $tracks_file > $temp_file
  234.         num_tracks=$(wc -l $temp_file)
  235.         if [ $"num_tracks" = "0" ] ;then
  236.           echo no tracks found for $cdfile
  237.         else
  238.            {
  239.               echo
  240.               echo "$cdtitle :-"
  241.               echo
  242.               cut -f 2 -d, $temp_file
  243.               echo
  244.            } | ${PAGER:-more}
  245.         fi   
  246.      fi
  247.      get_return;
  248.      return;
  249. }


  250. rm -f $temp_file;
  251. if [ ! -f $title_file ];then
  252.    touch $title_file;
  253. fi

  254. if [! -f $tracks_file ];then
  255.   touch $tracks_file;
  256. fi

  257. clear;
  258. echo
  259. echo
  260. echo "Mini CD manager";
  261. sleep 1

  262. quit=n;
  263. while [ "$quit" != "y" ];do
  264.    set_menu_choice;
  265.    case "$menu_choice" in
  266.     a)  add_records;;
  267.     r)  remove_records;;
  268.     f)  find_cd y;;
  269.     u)  update_cd;;
  270.     c)  count_cds;;
  271.     l)  list_tracks;;  
  272.     b)
  273.         echo
  274.         more $title_file
  275.         echo
  276.         get_return;;
  277.     q | Q )  quit=y;;
  278.     *)  echo "Sorry,choice not recognized";;
  279.     esac
  280. done

  281.     rm -f $temp_file
  282.     echo Finished
  283.     exit 0
复制代码
代码可运行,在学习的过程中,楼主有些疑问想不通,测试也搞不清楚,还望各位大大赐教.

1.echo -e "enter type \c"
  read tmp
这里面echo中的转义字符\c有什么作用?
我的解答:让输入停留在提示输入行,按回车后变量存入tmp中.去掉的话貌似输入不能被读取

2.用trap设置特定信号的信号处理函数的方法
trap - signalNumber
trap '' signalNumber
trap 'command to be executed' signalNumber
用户按Ctrl+C 退出时产生退出信号SIGEXIT
trap 'rm -f /tmp/songwolf/$temp_file' EXIT

3.shell脚本的调试的提示出错行数经常不对,有什么方法可以准确定位错误语句块

4.cut的用法
cut -f 2 -d, $temp_file表示什么意思?
表示:指定从$temp_file中以,为分隔符,取第二个字段(没有指定-s的情况下将把不包含分隔符的行也输出)

5.可以总结出一个用法如果$file中只有一行每行对应N个字段,字段分隔符为,则可以通过以下方法读出各字段里的值:
IFS = ","
read $var1,$var2...$varN < $file
IFS = "";

更一般地要从含N行的文件$file中分字段读出其第n行数据($file以逗号分割,N>=1, n between 1 and N)

第n行含有的记录数:
IFS = ",";
set $(head -n n $file|tail -1);
fieldNum = $?;
IFS = "";

6.上述问题用cut命令怎么解决呢?能不能对cut的用法做个介绍?
我的解答:cut类似于简单的awk函数
cut -f1,2 -d, $temp_file 通常等价于  awk -F',' 'BEGIN{OFS=","}{print $1,$2}' $temp_file

7.get_confirm定义如下:
get_confirm()
{
    echo -e "Are you sure? \c";
    while true
    do
       read x
       case "$x" in
         y | yes | Y | Yes | YES )
           return 0;;
         n | no | N | No | NO )
           echo;
           echo "Cancelled"
           return 1;;
         *) echo "Please enter yes or no" ;;
       esac
    done
}
在主程序中有调用get_confirm函数的场景如下:

if get_confirm ; then
如果调用到get_confirm时输入'y',此时主程序中返回值为多少?怎么样才能获得这个返回值呢?是true还是false,我们可以测试一下
比如说我们在add_records中调用了get_confirm来跟用户交互是否需要增加唱片中曲目对应的记录,输入了'y',然后返回值是多少呢?
怎么样在调用主函数中获得这个数字返回值
PS:returnedStatus=$(get_confirm)这种做法不行,因为$(command)是将command命令执行结果返回给主程序

论坛徽章:
0
2 [报告]
发表于 2011-03-02 18:26 |只看该作者
回复 1# regansong


    这还简单?

论坛徽章:
0
3 [报告]
发表于 2011-03-02 18:32 |只看该作者
回复 2# wtuter


    麻烦大大帮我解答下面那几个问题

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2011-03-02 18:59 |只看该作者
3.shell脚本的调试的提示出错行数经常不对,有什么方法可以准确定位错误语句块
这个怎么说?

其它的不是都知道了吗?

论坛徽章:
0
5 [报告]
发表于 2011-03-02 19:03 |只看该作者
就是说可能显示语法错误在304行,但是其实代码在前面第90几行有错误,通过什么办法才能定位到90几行.
还有代码shell脚本检查语法错误的时候是从第一行开始检查起的吗?如果对于一个比较大的脚本怎么才能高效率地调试呢?

还有,从函数get_confirm里面exit 0了,为什么调用函数get_confirm后if get_confirm是true的呢?这里条件测试的不是返回值吗?

论坛徽章:
0
6 [报告]
发表于 2011-03-02 19:44 |只看该作者
回复 1# regansong


举个简单的例子:
var=`echo xxx
echo 1
echo 2


执行脚本会提示第3行报错,但我们知道其实错在第1行少了个`,没有匹配。
这是因为shell脚本是逐行执行的,在第1行时发现`,shell一直在等待下一个`的出现,直到最后一行执行完了,shell发现不可能
再等到这个`了,于是提示第3行出错。

shell脚本的很多语法错误都类似这样,因为shell脚本是逐行执行的。

论坛徽章:
0
7 [报告]
发表于 2011-03-02 19:47 |只看该作者
谢谢,第3个明白了.
那第1个和第7个?
为什么要加上一个 \c?
为什么测试get_confirm时,get_confirm退出码是0,但是测试仍为true?

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
8 [报告]
发表于 2011-03-02 20:06 |只看该作者
谢谢,第3个明白了.
那第1个和第7个?
为什么要加上一个 \c?
为什么测试get_confirm时,get_confirm退出码 ...
regansong 发表于 2011-03-02 19:47
用$?获取上次命令退出的代码。
get_comfirm
if [ $? == 0 ]; then
...
fi
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP