免费注册 查看新帖 |

Chinaunix

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

[游戏娱乐] 2012年ChinaUnix社区Shell编程大赛 [结束评审 公布部分答案](获奖名单已公布-5-24) [复制链接]

论坛徽章:
0
21 [报告]
发表于 2012-03-08 10:45 |只看该作者
什么东西???

论坛徽章:
0
22 [报告]
发表于 2012-03-08 11:54 |只看该作者
第一题: 第一个单引号内是模糊匹配空格,第二个是中括号【】内精确匹配空格,第三个是精确匹配多个空格
第二题:awk打印所有匹配行,sed只打印第二个匹配单词的行

论坛徽章:
8
摩羯座
日期:2014-11-26 18:59:452015亚冠之浦和红钻
日期:2015-06-23 19:10:532015亚冠之西悉尼流浪者
日期:2015-08-21 08:40:5815-16赛季CBA联赛之山东
日期:2016-01-31 18:25:0515-16赛季CBA联赛之四川
日期:2016-02-16 16:08:30程序设计版块每日发帖之星
日期:2016-06-29 06:20:002017金鸡报晓
日期:2017-01-10 15:19:5615-16赛季CBA联赛之佛山
日期:2017-02-27 20:41:19
23 [报告]
发表于 2012-03-08 13:09 |只看该作者
本帖最后由 waker 于 2012-03-08 13:38 编辑

先试试1-8题吧
第一题:
awk -F ' ' 这等同于缺省设置,以"空白"分割域,并忽略行首尾的"空白"
awk -F '[ ]' 以单个空格符分割域,多个空格之间将产生"空域",空格符位于行首尾将产生"空域"
awk -F '[ ]+'以连续空格符分割域,连续空格符位于行首尾将产生"空域"
第二题:不一样,awk会对每行都匹配两个模式,而sed匹配到第一个模式后会在"下面"行中尝试匹配第二个模式
例子

  1. [waker@freebsd ~]$ cat urfile
  2. barfoo
  3. foo1,foo2
  4. foobar
  5. foo2
  6. [waker@freebsd ~]$ awk '/foo1/,/foo2/' urfile
  7. foo1,foo2
  8. [waker@freebsd ~]$ sed -n '/foo1/,/foo2/p' urfile
  9. foo1,foo2
  10. foobar
  11. foo2
复制代码
第三题:
  1. echo {a,b,c,e,f}{1,2,3}
复制代码
第四题:
不太明白,猜一下吧
  1. echo 'aaabcccaaabbbccceeeaaaffcccaaabbbffccc'|sed 's/\(\(.\)\2*\)/\1\n/g;:a;s/\([^ ]\+\n\)\(.*\n\)\1/\1\2/;ta;s/\n//g'
复制代码
第五题: 既然双引号中的\<newline>是续行符,为什么结果不是"foo  barabc def"?
因为我们通常讨论的\转义啊" '引用啊是在讨论shell如何解释命令,而这个命令替代中的\<newline>是从子进程的标准输出来的,暂时和转不转义没有关系?
在命令替代发生以后通过shell又要来解释替代取得的结果的时候,由于""引用的保护,echo 命令只有一个参数,`foo  bar\
abc def';文件的内容就"原样"输出了

第六题: 同第五题,在命令替代发生以后通过shell又要来解释替代取得的结果的时候,因为没用引用,替代的结果进行一次单词分割(word  splitting),
echo 有四个参数 `foo'  `bar\' `abc' `def',两个空格变一个其实是:2-2+1=1

第七题:
如果确定c不在最后一行
  1. echo '/a/,?c?p'|ed -s urfile
复制代码
如果不能确定的话
  1. ed -s urfile <<\EOF
  2. /a/ks
  3. g/c/ke
  4. `s,`ep
  5. q
  6. EOF
复制代码
第八题:

  1. seq 9|awk '{a[NR]=$0}END{for(i=1;i<NR;i++)print a[i],a[i+1],a[i+2]}'
复制代码
  1. seq 11|sed   'N;:a;N;s/\n/ /gp;s/[^ ]* //;ta'
复制代码

论坛徽章:
0
24 [报告]
发表于 2012-03-08 13:24 |只看该作者

论坛徽章:
0
25 [报告]
发表于 2012-03-08 16:04 |只看该作者
反正没人看的见

论坛徽章:
0
26 [报告]
发表于 2012-03-08 16:35 |只看该作者
第一题:
三者没区别

第二题:
实现的功能一样

第三题:
for i in `echo a b c e f`; do for j in `echo 1 2 3`; do echo $i $j; done; done

第四题:
$ cat file
aaabcccaaabbbccc
$ sed "s/\(aaa\)\(b\)\(ccc\).*\(bbb\).*/\1\2\3\4/" file
aaabcccbbb

第五题:
echo如果字符串带双引号时,会保留原来的格式不变打印出来,所以结果不是"foo barabc def"

第六题:
echo如果字符串不带双引号,就会用echo默认的间隔符,即空格,打印字符串,所以foo与bar之间只有一个空格

第七题:
sed -n '/a/,$p' file | tac | sed -n '/c/,$p' | tac

第八题:
for i in `seq 7`; do echo `seq $i $(($i+2))`; done; echo 8 9

第九题:
#! /usr/bin/env bash
#
USER="oracle"
HOST="client"
PASSWORD=""
array1=(a b c d e f g h i j k l m n o p q r s t u v w x y z)
array2=(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)
array3=(0 1 2 3 4 5 6 7 8 9)

NUM=$(($RANDOM % 26))
PASSWORD=${PASSWORD}${array1[$NUM]}
NUM=$(($RANDOM % 26))
PASSWORD=${PASSWORD}${array2[$NUM]}
NUM=$(($RANDOM % 10))
PASSWORD=${PASSWORD}${array3[$NUM]}

for i in `seq 5`; do
    NUM=$(($(($RANDOM % 3))+1))
    if [ $NUM == 3 ]
        NUM=$(($RANDOM % 10))
        PASSWORD=${PASSWORD}${array3[$NUM]}
    elif [ $NUM == 2 ]
        NUM=$(($RANDOM % 26))
        PASSWORD=${PASSWORD}${array2[$NUM]}
    elif [ $NUM == 1]
        NUM=$(($RANDOM % 26))
        PASSWORD=${PASSWORD}${array1[$NUM]}
    fi  
done

for i in `seq -w 1000`; do
    ssh $USER@$HOST$i #But it must login without password.
    (sleep 1; echo $PASSWORD; sleep 1; echo $PASSWORD; sleep 1) | passwd $USER
    if [ $? == 0 ]
        echo "[$HOST$i] : Modify password successfully." >> logfile
    else
        echo "[$HOST$i] : Modify password failed." >> logfile
    fi  
done

exit 0

论坛徽章:
0
27 [报告]
发表于 2012-03-08 16:41 |只看该作者
报名

论坛徽章:
0
28 [报告]
发表于 2012-03-08 18:39 |只看该作者
本帖最后由 xinyv 于 2012-03-09 09:40 编辑
  1. # 01
  2. awk -F ' '    # echo -ne "a b\tc    d"|awk -F ' ' '{print NF}'    # 匹配 1个或多个 空格 \t 就是 [\s]   答案为 4
  3. awk -F '[ ]'  # echo -ne "a b\tc    d"|awk -F '[ ]' '{print NF}'  # 只匹配 1 个空格 不包括 其他的如 \t 答案为 6
  4. awk -F '[ ]+' # echo -ne "a b\tc    d"|awk -F '[ ]+' '{print NF}' # 匹配多个空格 不包括 其他的如 \t    答案为 3
  5. # 02
  6. awk '/foo1/,/foo2/'  sed -n '/foo1/,/foo2/p' # 完全一样。{至少我不知道区别}
  7. # 03
  8. echo {a..f}{1..3}
  9. # 04
  10. awk 'BEGIN{split("aaabcccaaabbbccc",str,"");for(i=1;i<=length(str);i++){
  11.      if(s!~str[i]){if(newstr!~s)newstr=sprintf("%s%s",newstr,s);s=str[i]}else s=sprintf("%s%s",s,str[i])}print newstr}'
  12. # 05 06
  13. # 先明白 bash 转义字符有几个过程, 情况 (1 read stdin) 读取用户输入的时候转义, 情况 (2 write stdout,stderr) 输出屏幕的时候转义 情况 (3 read other) 不做任何转义
  14. # (1) 里面 " 的作用是除了 $ ` \ 外全部保持原有字符形式. \ 用来转义的字符只有 [$] [`] ["] [\] [\n] 这五种有效
  15. # (2) 里面 只进行 Console code IFS 扩展 即替换 [ ] [\t] [\n] 为一个空格 如果有 " 不扩展保留原有样子
  16. # 而题目里没有 (1) 这个过程,而是从文件读取(3), bash 会完整获取文件内容而不转义
  17. # 这里 \<newline> 根本不是什么续行符, 就是普通字符 直接进入 (2)
  18. # 第五个问题,因为有 ["] bash 保持完整输出,当然就是原来的样子
  19. # 第六个问题,bash 按照 (2) 扩展到条件把 [ ] [\t] [\n] 扩展为一个空格,结果当然就是那个样子

  20. # 07
  21. awk '{if($0=="a")S++;if(S)arr[++i]=$0;if($0=="c"){for(x in arr)print arr[x];delete arr}}' urfile
  22. # 08
  23. seq 9|awk '{A[0]=$0;getline;A[1]=$0;while(getline){printf("%s %s %s\n",A[0],A[1],$0);A[0]=A[1];A[1]=$0}print A[0],A[1]}'
  24. seq 9|sed -n 'N;:a;N;s/\n/ /g;s/\([^ ]\+\) \([^ ]\+\) \([^ ]\+\) \([^ ]\+\)/\2 \3 \4/;p;$s/\([^ ]\+\) //p;ta'
  25. # 09
  26. pwd=$(mkpasswd -l 8 -d 1 -c 1 -C 1)
  27. for i in seq -w 1000;do
  28.   (
  29.   ssh -o PasswordAuthentication=no client${i} -i sskkey passwd --stdin oracle <<<"${pwd}"
  30.   echo "client${i} $?" >>alog
  31.   ) &
  32. done
  33. wait
  34. echo $pwd >>alog
  35. # 10
  36. mysql -umyuser -pmypass -e "select id,email from dbSecond.employee2 order by id" >mysql.txt
  37. sqlplus -S myuser/mypass/nolog > oracle.txt <<EOF
  38. set heading off
  39. set feedback off
  40. set pagesize 0
  41. set verify off
  42. set echo off
  43. select id,email from employee1 order by id;
  44. exit;
  45. EOF
  46. diff -iy --suppress-common-lines mysql.txt oracle.txt|awk '{if($1!=$4)print $0 >>"different_id.txt";if($2!=$5)print $0 >>"different_email.txt"}'
复制代码

论坛徽章:
0
29 [报告]
发表于 2012-03-08 19:13 |只看该作者
本帖最后由 relvigour 于 2012-03-08 19:23 编辑

第一题
01.awk -F ' '    连续空白字符(包括\t、空格等)作为分割符
02.awk -F '[ ]'  单个空格键作为分割符
03.awk -F '[ ]+'  连续空格作为分割符

第二题
01.awk '/foo1/,/foo2/'               打印同时匹配 /foo1/ 和 /foo2/的行
02.sed -n '/foo1/,/foo2/p'   打印第一个匹配 /foo1/ 到第一个匹配 /foo2/之间所有的行

第三题
01.如何用最简单的方法列举出 "a b c e f" 和"1 2 3" 的所有组合?
法一:for x in a b c e f;do for y in 1 2 3;do echo $x $y;done;done
法二:seq 3|awk 'BEGIN{split("abcef",a,"")}{for(x in a){print a[x],$0}}'


第四题  暂时还没有找到优雅的方式。 
awk -v V='aaabcccaaabbbccc' 'END{
    split(V,a,"");
    lastchar=a[1];
    lastword=a[1];
    for(i=2;i<=length(a);i++){
          if(a!=lastchar){
               d[lastword]++
               if ( d[lastword] ==1)
                       printf lastword
               lastchar=a ;
               lastword=a ;
          }else
               lastword=lastword""a
   }
}'  < /dev/null


第五题: "$(<urlfile)"  因为变量的内容是从文件中读取的,而续行符是Shell是将命令行解析成变量内容时候用进行
第六题: echo 输出的时候会将所有的空白字符(含回车、tab 等)用空格键替换。



第七题:  sed -n '/a/,$H;/c/bt;b;:t x;p;n;h;'  file

第八题:  seq 9 | awk '{l=m" "$0;m=n" "$0;n=$0;}NR>2{print l}END{print m}'

第九题:
M='0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
while [ "x$V" != "x7" ] ; do
      V=0;P=;
      for((n=1;n<9;n++)); do
              m=$(($RANDOM%${#M}));
              [ $m -le 10 ] && V=$((V|1)) || [ $m -le 36 ] && V=$((V|2)) || [ $m -le 62 ] && V=$((V|4)) ;
              P="$P${M:$m:1}" ;
      done
done
echo "New Password:" $P > result.txt
seq -w 1000 | while read id ; do
   if   echo "$P"|ssh root@client$id passwd oracle --stdin   ; then
        echo  client$id  OK . >> result
   else :
                   echo  client$id  Failed . >> result
done


第十题:
# get oracle data
cat -<< "EOF" |sqlplus -s myuser/mypass@dbFirst  > oracle.txt
  set feedback off
  set hea off
  set newp 0
  SELECT ID , EMAIL FROM employee1
  /
EOF

# get mysql  data
echo " select  id , email  from employee2 ;" |mysql -B -u myuser --password=mypass dbSecond > mysql.txt

awk '{a[$1]++;b[$2]++}
END{for(x in a)if(a[x]==1)print x > "different_id.txt"
    for(y in b)if(b[y]==1)print y > "different_email.txt"
}' mysql.txt  oracle.txt

论坛徽章:
33
ChinaUnix元老
日期:2015-02-02 08:55:39CU十四周年纪念徽章
日期:2019-08-20 08:30:3720周年集字徽章-周	
日期:2020-10-28 14:13:3020周年集字徽章-20	
日期:2020-10-28 14:04:3019周年集字徽章-CU
日期:2019-09-08 23:26:2519周年集字徽章-19
日期:2019-08-27 13:31:262016科比退役纪念章
日期:2022-04-24 14:33:24
30 [报告]
发表于 2012-03-08 20:00 |只看该作者
回复 29# relvigour


建议把代码放到code标签里面,否则会丢失字符。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP