免费注册 查看新帖 |

Chinaunix

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

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

论坛徽章:
49
15-16赛季CBA联赛之福建
日期:2016-06-22 16:22:002015年亚洲杯之中国
日期:2015-01-23 16:25:12丑牛
日期:2015-01-20 09:39:23未羊
日期:2015-01-14 23:55:57巳蛇
日期:2015-01-06 18:21:36双鱼座
日期:2015-01-02 22:04:33午马
日期:2014-11-25 09:58:35辰龙
日期:2014-11-18 10:40:07寅虎
日期:2014-11-13 22:47:15申猴
日期:2014-10-22 15:29:50摩羯座
日期:2014-08-27 10:49:43辰龙
日期:2014-08-21 10:47:58
11 [报告]
发表于 2011-05-16 09:41 |只看该作者
1.find . -maxdepth 1 -ls
问题2:
GNU sed 提供了-i选项,为什么有人说sed -i 并不象 ed 一样 ...
南极雨 发表于 2011-05-16 06:51



   
凑凑热闹

1:2:
因为sed -i的执行过程:先产生一个临时文件,然后把结果输出到这个文件,
最后把这个文件重 ...
yinyuemi 发表于 2011-05-16 05:11



   
沙发???

突然感觉自己水平好烂好烂,估计能答对一半就不错了……
总觉得第一个回答的人有点亏啊,有 ...
xiaopan3322 发表于 2011-05-15 23:57



   
sorry,各位,第7题题目有所变化,请大家重新考虑一下答案:)

各位答题还挺快的啊,呵呵

论坛徽章:
0
12 [报告]
发表于 2011-05-16 10:28 |只看该作者
本帖最后由 xiaofengmanlou 于 2011-05-16 14:04 编辑

呵呵,看了遍题,发现很多不会的,
不过发现了差距,才能进步。
先把知道的回答下,参与一下,呵呵
1.find  -maxdepth 1 -mindepth 1 -type d。这样不包含当前目录本身
2.因为ed是直接在原文件上进行编辑,而sed -i是先创建临时文件,然后在临时文件上进行编辑
3.暂时没想到,呵呵
4.不一样。
5.先对test.txt文件做备份,再读取/script/scr.sedcc的内容作为sed的命令来处理test.txt(想起来,这里的-if应该要分开写吧,连在一起不能执行)
6.exec tclsh "$0" "$@" 表示用tclsh来执行当前的脚本及其参数,并替换当前的shell
7.不能。因为-f后要指定sed要读取的命令文件。如果跟着其它的参数,会被当成文件名。
假如
#!/bin/sed -f -n
运行会报这种错误:
/bin/sed: couldn't open file  -n: No such file or directory
8.$1=$1这个应该算是个伪 表达式或条件,当在BEGIN中指定了OFS时,如果在awk的程序主体中不进行任何操作,awk会认为结果没有变化,会原样输出。这里应该只要是表示真的表达式都可以。
9.
10.

论坛徽章:
0
13 [报告]
发表于 2011-05-16 10:49 |只看该作者
俺再解释一下问题三吧,回答过的可以重新回答

本地是指客户端机器,CGI脚本由web服务器运行,二者在逻辑 ...
waker 发表于 2011-05-16 08:37



    哈哈,多谢版主再给一次机会,已重新回答……

论坛徽章:
16
IT运维版块每日发帖之星
日期:2015-08-24 06:20:00综合交流区版块每日发帖之星
日期:2015-10-14 06:20:00IT运维版块每日发帖之星
日期:2015-10-25 06:20:00IT运维版块每日发帖之星
日期:2015-11-06 06:20:00IT运维版块每日发帖之星
日期:2015-12-10 06:20:00平安夜徽章
日期:2015-12-26 00:06:302016猴年福章徽章
日期:2016-02-18 15:30:34IT运维版块每日发帖之星
日期:2016-04-15 06:20:00IT运维版块每日发帖之星
日期:2016-05-21 06:20:00综合交流区版块每日发帖之星
日期:2016-08-16 06:20:002015七夕节徽章
日期:2015-08-21 11:06:17IT运维版块每日发帖之星
日期:2015-08-14 06:20:00
14 [报告]
发表于 2011-05-16 11:22 |只看该作者
第一题 ls -l ./* 就可以了吧?
第二个 sed的-i应该写入了临时文件里,然后再保存的。inode有变化

第三题,题目没太看明白,cgi脚本?是

第4题,是一样的,测了下

Q5:执行脚本,并且保存结果.

Q6:不会,囧

Q7:可以的吧,#后全是注释吧。

Q8,很常见的,论坛经常出现。但我不喜欢这个写法,so,也不会

Q9: 这个题要好好搞下,比较实用。站位。

Q10:这题有点难,应该是分数比重最高的

论坛徽章:
0
15 [报告]
发表于 2011-05-16 11:24 |只看该作者
我自认功力不足...

不过第一题怎么没人 ls */
惟吾无为 发表于 2011-05-16 08:02



    看清题目,一级子目录

论坛徽章:
1
巳蛇
日期:2013-10-28 15:55:33
16 [报告]
发表于 2011-05-16 12:13 |只看该作者
看清题目,一级子目录
xiaopan3322 发表于 2011-05-16 11:24

o, 理解成子目录内容了.
ls -d */

论坛徽章:
0
17 [报告]
发表于 2011-05-16 12:48 |只看该作者
本帖最后由 justlooks 于 2011-05-17 09:44 编辑

第8题
$1=$1大家都知道了,补充下$0=$0

  1. echo "aa bb"|awk '{$2="c d";}{print $2" "NF}$0=$0{print $2" "NF}'
  2. c d 2
  3. c 3
复制代码
第5题

  1. 没仔细审题,擦掉,呵呵
复制代码

论坛徽章:
1
摩羯座
日期:2014-12-29 15:59:36
18 [报告]
发表于 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. }
复制代码
都没有考虑子版块!

论坛徽章:
0
19 [报告]
发表于 2011-05-16 14:52 |只看该作者
回复 2# xiaopan3322


    弱弱的问下 (echo "contents"; uuencode urfile file)

你这句什么意思???

谢谢!

论坛徽章:
0
20 [报告]
发表于 2011-05-16 15:15 |只看该作者
回复  xiaopan3322


    弱弱的问下 (echo "contents"; uuencode urfile file)

你这句什么意思?? ...
db2-zhang 发表于 2011-05-16 14:52



    前半句邮件内容,后半句邮件附件
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP