免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: send_linux
打印 上一主题 下一主题

ChinaUnix技术实践之四----Shell编程大赛! [复制链接]

论坛徽章:
1
摩羯座
日期:2014-12-29 15:59:36
1 [报告]
发表于 2011-05-16 14:27 |显示全部楼层
本帖最后由 ziyunfei 于 2011-08-19 10:19 编辑

慢慢答

1.     ls -Ad */


2.     ls -i 可以查看文件的inode,前后不一样.说明是sed删除并新建了文件.和vim一样


3.
  1. #!E:\Cygwin\bin\bash.exe
  2. echo -e "Content-type: text/html\n"
  3. if [[ "$REQUEST_METHOD" = "GET" ]];then
  4.         cat<<EOF
  5.         <html>
  6.         <head>
  7.         <title>发送邮件</title>
  8.         <meta http-equiv="Content-Type" content="text/html; charset=GB2312">
  9.         </head>
  10.         <body bgcolor="#9898BA" text="#000000">
  11.         <hr size="5">
  12.         <form method="post" enctype="multipart/form-data">
  13.         <label for="file"> 收件人: </label>
  14.         <input name="email" id="email" type="text“>
  15.         <label for="file"> 附件: </label>
  16.         <input name="file" id="file" type="file">
  17.         <input name="submit" value="发送" type="submit">
  18.         </form>
  19.         </body>
  20.         </html>
  21. EOF
  22. else
  23.         cat>post                           #post内容保存到post文件
  24.         email=$(awk 'NR==6{print}' post)      #得到email地址
  25.         name=$(awk -F'"' 'NR==6{print $4}' post)   # 得到上传文件名
  26.         lines=$(wc -l post|awk '{printf $1}')                #得到post文件行数
  27.         start=$(($lines-8))                                           #得到上传文件在post文件的起始行
  28.         end=$(($lines-13))                                           #得到上传文件在post文件的结束行
  29.         tail -n $start post|head -n $end > "$name"       #从post文件抽取出二进制文件
  30.         uuencode "$name" |mail -s mail $email             #发送邮件
  31.         rm post "$name"                                               #删除临时文件
  32.         echo "发送成功"
  33. fi
复制代码


4.    不一样,这个是shell本身的行为.和awk没啥关系

awk -F''  shell处理后awk只有一个参数 相当于awk -F
awk -F '' shell处理后awk有两个参数,一个是-F 一个是NULL

其他程序也一样ls'' 可以运行, ls '' 就不对了.甚至"l"s''也对

Effective AWK Programming 一书和awk manual里也专门指出了这种情况

Null strings are removed when they occur as part of a non-null command-line argument, while explicit non-null objects are kept. For example, to specify that the field separator FS should be set to the null string, use:

          awk -F "" 'program' files # correct

Don't use this:

          awk -F"" 'program' files  # wrong!

In the second case, awk will attempt to use the text of the program as the value of FS, and the first file name as the text of the program! This results in syntax errors at best, and confusing behavior at worst.




5. sed -if /script/scr.sedcc test.txt   f被当成-i的参数, 生成备份文件test.txtf /script/scr.sedcc是脚本,写明白就是 sed -if '/script/{s/r.sed//}' test.txt

6.和7题一样,关键是能添加多个参数

7.看运行方式,如果是是sed -f 脚本名 就可以,不过出题的意思应该是./脚本名,那就不行.试着解释一下

假如在-f后面添加个参数 #!/bin/sed -f -r,提示无法打开文件 -r,有人说:把-r 放 -f 前面行不行呢,答案是不行

我们不知道shell解释#!的时候到底传给了sed什么样的参数.所以我们自己写个脚本来充当sed的角色

就叫sed.sh
  1. #!/bin/bash
  2. echo "我是$0"
  3. echo "参数1=$1"
  4. echo "参数2=$2"
  5. echo "参数3=$3"
  6. echo  "完整命令为 $0 $@"
复制代码
在写一个脚本,sh.sh,用来调用我门的sed
  1. #!./sed.sh -f -r
复制代码
然后在shell里执行 ./sh.sh a.txt,模拟用sed 调用 sh.sh 来处理a.txt

sed.sh反回的结果是
  1. 我是sed.sh
  2. 参数1=-f -r
  3. 参数2=./sh.sh
  4. 参数3=a.txt
  5. 完整命令为sed.sh -f -r ./sh.sh a.txt
复制代码
也就是shell把-f -r 当成一个参数传给了sed.sh,把f和r换过来,完整命令是sed.sh -r -f ./sh.sh a.txt,好像是正确的,但其实对应的shell命令是sed.sh "-r -f" ./sh.sh a.txt,明显不对

如果 这样执行 sed.sh -f sh.sh a.txt,sed就把shebang就当成解释了,怎么写都无所谓了

8.$1=$1 是用来激活$0的重新赋值,也就是说 字段$1...和字段数NF的改变会促使awk重新计算$0的值,通常是在改变OFS后而需要输出$0时这样做

    echo "A B C D" | awk '{OFS="|";print $0;$1=$1;print $0;}'
    A B C D
    A|B|C|D
   
    即使OFS放在BEGIN里,也没有用
    echo "A B C D" | awk 'BEGIN{OFS="|"}{print $0;$1=$1;print $0;}'
    A B C D
    A|B|C|D

   $0=$0 刚好相反, 修改$0的值可以促使awk重新计算字段$1...和字段数NF的的值,通常是在改变FS后而需要输出$1...或者NF时这样做

    echo "A|B|C|D" | awk '{FS="|";print $1,NF;$0=$0;print $1,NF}'
    A|B|C|D 1
    A 4
   
    不过把修改FS放在BEGIN里,就没必要$0=$0了
    echo "A|B|C|D" | awk 'BEGIN{FS="|"}{print $1,NF;$0=$0;print $1,NF}'
    A 4
    A 4
   
其实,在awk源码中.重新计算$0的值的函数名叫rebuild_record,重构记录的意思.默认情况下.这个函数是不可能执行的.因为$0是直接读入的.$1=$1等修改字段的行为会触发awk执行这个函数
重新计算$1...的值的函数名叫reset_record,重新分割记录到字段的意思.默认情况下.这个函数只在处理完当前行,读入下一行之前执行.中途是不会执行的.$0=$0等修改记录的行为会触发awk执行这个函数
通过在源码中添加一行标记重新编译awk.可以查看awk到底什么时候运行了这两个函数.

rebuild_record
  1. echo "A B C D" | awk '{print $0;OFS="|";print "OFS=\"|\"";print $0;print "$1=$1";$1=$1;print $0;}'
  2. -----------reset_record-----------             #读入行之前,执行reset_record,把$0拆分开赋值给$1...
  3. A B C D                                         #$0为读入的值
  4. OFS="|"                                        #改变OFS
  5. A B C D                                         #没有触发rebuild_record重构$0,$0仍为读入的值.
  6. $1=$1                                           #执行$1=$1,
  7. ----------rebuild_record------------            #awk不管$1是否真的改变,执行rebuild_record.
  8. A|B|C|D                                         #$0的值成为各个字段和ORS计算出的值
复制代码
reset_record
  1. echo "A|B|C|D" | awk '{print $1,NF;print "FS=\"|\"";FS="|";print $1,NF;print "$0=$0";$0=$0;print $1,NF}'
  2. -----------reset_record-----------              #读入行之前,执行reset_record,把$0拆分开赋值给$1...
  3. A|B|C|D 1                                        #$1为刚才计算的值
  4. FS="|"                                             #改变FS
  5. A|B|C|D 1                                        #没有触发reset_record重构$1和NF,仍为第一次计算的值.
  6. $0=$0                                             #执行$0=$0
  7. -----------reset_record-----------              #awk不管$0是否真的改变,执行reset_record.
  8. A 4                                                   #$1和NF的值成为重新计算出的值
复制代码
9.
awk命令行,调用curl和grep.
  1. awk 'BEGIN{a="http://bbs.chinaunix.net/";while("curl -s "a"|grep -oP \"forum-.+-.+.html(?=. >)\""|getline b){c=c" "a""b;}while("curl -s"c"|grep -oP \"<title>.*? |(?<=版主: ).*?p>$|无权访问\""|getline d){e=gensub("<[^>]*>","","g",d);if(f==0){printf e;f++;g++}else{print ": "e;f--;split(e,h,", ");i[0];for(j in h){if(!(h[j] in i)){k++;i[h[j]]}}}}print g" : "k-2}'
复制代码
awk脚本,awk访问网络.
  1. #!/usr/bin/gawk -f
  2. BEGIN{
  3.         bbs = "http://bbs.chinaunix.net"
  4.         bbsHtml = getHtml(bbs);
  5.         while(match(bbsHtml,/forum(-[0-9]+){2}.html. >/)){
  6.                 thread = bbs"/"substr(bbsHtml,RSTART,RLENGTH-3);
  7.                 ++threadSum;
  8.                 bbsHtml = substr(bbsHtml,RSTART+RLENGTH);
  9.                 threadHtml=getHtml(thread);
  10.                 match(threadHtml,/<title>[^ ]* /);
  11.                 print "\033[32m"gensub(/<[^>]*>/,"","g",substr(threadHtml,RSTART,RLENGTH))"\033[m";
  12.                 if(match(threadHtml,/版主: [^\n]*a><.p>/)){
  13.                         bz= gensub(/<[^>]*>/,"","g",substr(threadHtml,RSTART,RLENGTH));
  14.                         print bz;
  15.                         split(substr(bz,5),sum,", ");
  16.                         for(i in sum){
  17.                                 if (!(sum[i] in bzsum))
  18.                                         bzSum[sum[i]]=1;
  19.                         }
  20.                 }
  21.                 else if(match(threadHtml,/无权访问/)){
  22.                         print "无权访问";
  23.         }
  24.         else{
  25.                 print "版主: *空缺中*";
  26.   }
  27. }
  28. print "\033[32m统计\033[m\n板块数:"threadSum" 版主数:"length(bzSum);
  29. }
  30. function getHtml(url){
  31.         host=gensub("^http://|/.*","","g",url);
  32.         path=gensub("^http://[^/]*/?","/","g",url);
  33.         socket="/inet/tcp/0/"host"/80";
  34.         print "GET "path" HTTP/1.0\r\nHost: "host"\r\n\r" |& socket;
  35.         html="";
  36.         while((socket |& getline) > 0){
  37.                 html=html$0"\n";
  38.         }
  39.         close(socket);
  40.         return html;
  41. }
复制代码
都没有考虑子版块!

论坛徽章:
1
摩羯座
日期:2014-12-29 15:59:36
2 [报告]
发表于 2011-05-16 21:41 |显示全部楼层
回复  sosodream


    向楼上的第五题的精彩回答致敬……真的……
    看来大家都想当然了……
     ...
xiaopan3322 发表于 2011-05-16 21:34

为啥不向我致敬
这道题一看就有问题,不可能那么简单
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP