免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zooyo

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

论坛徽章:
0
发表于 2012-03-14 10:46 |显示全部楼层
本帖最后由 jiayanfu 于 2012-03-15 09:30 编辑

宗旨:求书一本!


1、
没有区别。都是以一个或者多个空格符作为分隔符。

2、
两者实现的功能不完全一样,
相同点:虽然都是模式匹配“从出现foo1到出现foo2”
不同点:
sed在匹配的时候,foo1 和 foo2 不能在同一条记录中被匹配,而awk则不然。例子如下

  1. root@localhost /opt/Linux_shell]$cat footest
  2. foo0
  3. foo1 foo foo2
  4. the end
复制代码
,  

awk的匹配结果是:
  1. foo1 foo foo2
复制代码
awk 认为匹配结束
sed的匹配结果是:
  1. foo1 foo foo2
  2. the end
复制代码
而sed认为foo2没有匹配到

3、
不知道最简单的方法是什么,我用了嵌套循环,应该不是最简单的。。。囧。。。。
  1. #/bin/sh

  2. for i in "1" "2" "3" "4" "5" "6"
  3. do
  4.         for j in "a" "b"
  5.                 do
  6.                         echo $i$j
  7.                 done
  8. done
复制代码
4、
题目的意思理解为:将字符串aaa和ccc的重复串消除掉。
题目使用sed实现,思路为:将第一次出现的aaa和 ccc分别替换为特殊字符,然后将整个字符串中的aaa和ccc清除掉,最后将aaa和ccc分别对应的特殊字符串再替换回来
实现语句如下:
  1. sed -n  -e 's/aaa/!/'   -e 's/ccc/@/'       -e 's/aaa//g'     -e 's/ccc//g'        -e 's/!/aaa/'  -e 's/@/ccc/p'
复制代码
5、
之所以会引起换行,是因为\后面还有一个ascii码为“0a”的换行符。
6、
如果不加双引号的话,urfile文件重定向输入的东西不再整体当做一个字符串来对待,会当做 零散的字符串,这时候的一个或者多个“空格”作为了分隔符来输入给echo命令。

7、
先倒着输出从c开始到结尾的所有行,然后使用管道,再倒着输出从a到结尾的所有行。
实现语句如下:
  1. tac file | sed -n '/c/,$p' | tac | sed -n '/a/,$p'
复制代码
8、
实现代码脚本如下:

  1. #!/bin/sh

  2. for i in 1 2 3 4 5 6 7 8 9
  3. do
  4.         seq 9 | sed -n "$i,9p" | paste -s | awk '{print $1,$2,$3}'
  5. done
复制代码

论坛徽章:
2
2015年迎新春徽章
日期:2015-03-04 09:55:28IT运维版块每日发帖之星
日期:2016-07-29 06:20:00
发表于 2012-03-14 10:57 |显示全部楼层
1.有区别,第1,2表示以一个空格为分隔符.3表示多个
2.不一样,1不会打印,2会打印修改的行
3.
a="a b c e f"
b="1 2 3"
for i in $a
do
for j in $b
do
echo $i,$j
done
done
4.使用echo管道,省去了创建文件的麻烦.echo 'aaabcccaaabbbccc'|awk -F 'bbb' '{print $1"bbb"}'
7.
8.这个应该用数组和循环来实现.

9.推荐一个工具mkpasswd,生成要求的密码使用如下命令
mkpasswd -s 0 -l 8.
至于printf命令,调整统计信息的格式.
10.diff命令是比较不同的,详细用法没研究过.

论坛徽章:
0
发表于 2012-03-18 22:59 |显示全部楼层
本帖最后由 chnliyong 于 2012-03-19 16:06 编辑

1
  1. awk -F ' '
  2. 是以空白符(包括空格space和制表符tab)分隔,只匹配一个字符,若出现两个连续空白符则匹配两次,中间被分割的串为空。
  3. awk -F '[ ]'
  4. 仅以空格space作为分隔符,也是只匹配一个空格
  5. awk -F '[ ]+'
  6. 仅以空格space作为分隔符,可以匹配连续出现的多个空格
复制代码
2
  1. 二者实现的功能是一样的,均先从匹配foo1的行开始打印到标准输出,直到出现匹配foo2的行为止
复制代码
4
  1. $ cat > file.txt
  2. aaabcccaaabbbccc
  3. $ sed -e 's/\(\([a-z]\)\2\+\)\(.*\)\1/\1\3/' -e 's/\(\([a-z]\)\2\+\)\(.*\)\1/\1\3/' file.txt
  4. aaabcccbbb
  5. $
复制代码
5
  1. 双引号中\<newline>当成成续行是shell提供的而并并非 echo 提供, echo "$(<urfile)"中urfile的内容作为一个字符串传递给 echo 程序, echo 程序将\<newline>当作两个字符(\和换行)输出
复制代码
6
  1. echo $(<urfile) 中urfile的内容作为参数传给 echo ,没有加引号, echo 将其当作多个字符串并以空白符作为分界,然后默认以一个空格作为间隔输出,所以多个空格,换行都被一个空格替代
复制代码
7
  1. tac file | sed -n '/^c/,$p' | tac | sed -n '/^a/,$p'
复制代码
8
  1. seq 9 | awk '{first = second; second = third; third = $0; if (NR >= 3) print first, second, third;} END{print second, third}'
复制代码

论坛徽章:
0
发表于 2012-03-21 15:16 |显示全部楼层
第一题:
awk -F 的作用是设置分隔符,当分隔符是一个时 可以直接写在F的后面
当分隔符是由多个字符组成时 必需使用' '引起
当分隔符有可能是多种字符组成时 可以用[ ]来表示,其用法同正则表达式
所以
awk -F ' '
awk -F '[ ]'
awk -F '[ ]+'
三者有区别,awk -F ' ' 和 awk -F '[ ]' 都表示分隔符为一个空格
而awk -F '[ ]+' 表示分隔符可以是一个或多个空格。

第二题:
他们的作用都是查找并打印从 匹配的foo1行 到foo2行
如果foo1 和foo2 不在同一行,他们的效果是一样的,但当foo1 和foo2 在同一行中时,awk 和sed 的处理就不一样了。
当foo2 和foo1 在同一行时,sed会跳过该foo2继续寻找下一个foo2,而awk则不会。

第三题:
$ cat 3.sh
#!/bin/bash
X="a b c e f"
Y="1 2 3"
for x in $X
do
        for y in $Y
        do
                printf "$x$y\n$y$x\n"
        done
done

第四题:


第五题:
由于使用了双引号 所以某些字元替换就被关闭了。依据shell处理步骤,先拆解字段,再看特殊字符(这里把该变量的值还原,但由于外层双引号的存在,所以变量中的 空格 和 \ 这些特殊字符被保留。)最终shell 把它们组合起来,echo 后面只有一个参数,urfile 被原封不动的打印出来。

第六题:
由于没有使用双引号 所以所有字元都被处理。依据shell处理步骤,先拆解字段,再处理特殊字符(在此替换变量的过程中,由于变量没有被引号括住,shell继续对其中的内容做处理,根据IFS拆解字段 foo 和bar 中的两个空格被当成一个空格,\ 后面的回车被转义……),最终sehll 把这些组合起来 echo后面出现了4个参数。打印结果如题目所示所有参数在一行显示且foo 和bar 中间只有一个空格。

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

第八题:
$ cat 8.awk
/[0-9]/{
        if ($1>
                ;
        else
                if($1==
                        printf"%d %d\n",$1,$1+1
                else
                        printf"%d %d %d\n",$1,$1+1,$1+2
}
       
$ seq 9 |awk -f 8.awk
1 2 3
2 3 4
3 4 5
4 5 6
5 6 7
6 7 8
7 8 9
8 9

第九题:

第十题:

论坛徽章:
0
发表于 2012-03-23 02:02 |显示全部楼层
1.awk -F 指定FS(字段分隔符),后接一个正则表达式。
第一个相当于FS的默认值,包括一个或多个空白字符(空格与制表字符)的情况,并会忽略掉行的开头和结尾的空白。
第二个是指字段分隔符正好匹配一个空格。
第三个是指字段分隔符匹配一个或多个空白字符,不会忽略行的开头和结尾的空白。
--------------------------------------------------------------------------------
2.区别:
sed -n '/foo1/,/foo2/p' 寻找foo2要从foo1所在的那行记录之后的记录开始(),不包括foo1所在的行记录
awk '/foo1/,/foo2/'     寻找foo2从foo1所在的那行记录开始,包括foo1所在的行记录
例如:
foo1 hello foo2
hello
foo2

sed -n '/foo1/,/foo2/p'会输出:
foo1 hello foo2
hello
foo2
而awk '/foo1/,/foo2/'仅会输出:
foo1 hello foo2
--------------------------------------------------------------------------------
3.
s="{1,2,3,4,5,a,b,c}";eval "echo $s$s$s$s$s$s$s$s"|tr ' ' '\n'|egrep -v '(\w).*\1'
想法很简单,但效率很低
--------------------------------------------------------------------------------
4.
echo 'aaabcccaaabbbccc'>tmp1.file;sed 's/&\n/g' tmp1.file>tmp2.file;awk '!found[$0]++' tmp2.file>tmp1.file;tr -d

'\n'<tmp1.file;rm -f tmp1.file tmp2.file
其实还是用管道.
--------------------------------------------------------------------------------
5.
因为$(...)命令替换把结尾的换行符(tailing newline)去掉了,而\必须后跟换行符才被解释为续行符。
6.
---------------------------------------------------------------------------------
系统默认的IFS为<space>,<tab>,<newline>。对于不加双引号的$(<urlfile)的情况,urlfile文件的内容被IFS分隔为四个字段,继而

成为echo的四个参数,所以结果就是那样了。
--------------------------------------------------------------------------------
7.
a在c之前的:
cat test|tr '\n' '#'|sed 's/^[^a]*//'|sed 's/[^c]*$s/^#//'|tr '#' '\n'
c在a之前的情况,将上式中的a和c互换一下就行了。
#是一个中介字符,要求在所有输入行中不存在。
--------------------------------------------------------------------------------
8.
seq 8|awk '{print $0,$0+1,$0+2;}'|sed 's/10//'
-------------------------------------------------------------------------------
9. 生成密码用到了mkpasswd,可以安装expect来获得这个命令
#!/bin/bash
#The file client.list contains the 1000 client ip address
#The file success contains the client for which the oracle password was updated successfully.
#The file failure.list contains the client for which there exited something wrong when updating password.


SUCCESS=0

for client in $(cat client.list)
do
   password=$(mkpasswd)
   result=$(echo $password|ssh $client passwd --stdin oracle)
   if [ "$?" -eq $SUCCESS ]
   then
        echo "client $client passowrd of oracle updated succesfully!"
        echo "$client     $password">>success.list
   else
        echo "Error occurred when updating the password of oracle for client $client"
        echo "$client     failure">>failure.list
   fi
done
----------------------------------------------------------------------------------
10.
用sqlplus spool方法将表数据存入两个文件employee1.txt,employee2.txt
文件output1.sql的内容为:
set head off
set headsep off
set newp none
set linesize 100
set pagesize 10000
set sqlblanklines off
set trimspool on
set termout off
set feedback off
spool employee1.txt
select id||' '||email from employee1;
spool off
exit

然后在命令行将表数据从远程数据库192.168.3.7存入employee1.txt(对于employee2表操作方法相同):
#!/bin/bash
sqlplus -S myuser/mypass@//192.168.3.7:1521/dbFirst @output1.sql
sqlplus -S myuser/mypass@//192.168.3.7:1521/dbSecond @output2.sql
awk 'print $1' employee1.txt>>employee1_id.txt
awk 'print $2' employee1.txt>>employee1_email.txt
awk 'print $1' employee2.txt>>employee2_id.txt
awk 'print $2' employee2.txt>>employee2_email.txt
sort -n  employee1_id.txt employee2_id.txt|uniq -u>different_id.txt
sort employee1_email.txt employee2_email.txt|uniq -u>different_email.txt

论坛徽章:
0
发表于 2012-03-24 15:23 |显示全部楼层
本帖最后由 Dreamhat 于 2012-03-24 15:46 编辑

环境:
Red Hat Enterprise Linux WS release 4 (Nahant Update 8 )
2.6.9-89.ELsmp #1 SMP Mon Apr 20 10:34:33 EDT 2009 i686 i686 i386 GNU/Linux

第一题:
有区别
  1. awk -F ' '
  2. 设定FS变量(输入域分隔符)为空格(一个或多个),或者tab(1个或多个),或者换行。而且会去除行首行末多余的空格
复制代码
  1. awk -F '[ ]'
  2. 设定FS变量(输入域分隔符)为一个空格
复制代码
  1. awk -F '[ ]+'
  2. 设定FS变量(输入域分隔符)为一个或者多个空格
复制代码
举个例子:

  1. [tlu@tlu-linux chinaunix]$ cat -A file
  2. aaa  bbb ccc^Iddd eee$
  3. 上面这个file文件里aaa之前是有个空格的,code里显示不出。
  4. [tlu@tlu-linux chinaunix]$ awk -F ' ' '{print $4}' file
  5. ddd
  6. [tlu@tlu-linux chinaunix]$ awk -F '[ ]' '{print $4}' file
  7. bbb
  8. [tlu@tlu-linux chinaunix]$ awk -F '[ ]+' '{print $4}' file
  9. ccc     ddd
复制代码

第二题:

  1. awk '/foo1/,/foo2/'
  2. sed -n '/foo1/,/foo2/p'
复制代码
这两个命令功能基本一样,但是有差异:
当foo1和foo2在同一行时,两者执行结果不同。
sed是行操作,找到有包含foo1的行时(同一行有无foo2不影响),打印开关(p)打开,然后再往下一行行的找foo2,如果找到了,打印开关就关闭。再往下如果找到foo1,打印开关再打开,如此反复直到文件末尾。
awk是先找foo1,然后找foo2(可以在同一行里),然后把找到的所有行打印出来,如此反复直到文件末尾。

例子:

  1. [tlu@tlu-linux chinaunix]$ cat file
  2. foo1foo2
  3. foo2
  4. foo1
  5. end
  6. [tlu@tlu-linux chinaunix]$ awk '/foo1/,/foo2/' file
  7. foo1foo2
  8. foo1
  9. end
  10. [tlu@tlu-linux chinaunix]$ sed -n '/foo1/,/foo2/p' file
  11. foo1foo2
  12. foo2
  13. foo1
  14. end
复制代码

第三题:
如何用最简单的方法列举出 "a b c e f" 和"1 2 3" 的所有组合?

  1. echo {a,b,c,e,f}{1,2,3}
复制代码

第四题:
字符串 'aaabcccaaabbbccc',连续的字母作为一个子字符串,从左往右,去重复后,变为 'aaabcccbbb' ,
awk或sed实现,不使用管道。

这道不太会

  1. echo 'aaabcccaaabbbccc' | sed 's#\(a\{1,\}\)\(b\{1,\}\)\(c\{1,\}\)\(a\{1,\}\)\(b\{1,\}\)\(c\{1,\}\)#\1\2\3\5#'
复制代码

第五题: 既然双引号中的\<newline>是续行符,为什么结果不是"foo  barabc def"?
echo "$(<urfile)"
这个命令是执行一个subshell运行<urfile,然后echo出来
需要用eval echo "$(<urfile)"再进行一次命令行处理,才能达到打印出"foo  barabc def"的效果

第六题:foo也bar之间为什么只有一个空格?
$()命令替换执行后,bash会根据$IFS中的字符做分割符进行从新分隔单词,所以多个空格,对echo看起来都一样的,是一个分隔符。

第七题:

  1. sed -n '/a/,'$(grep -n c file|tail -1|awk -F: '{print $1}')p'' file
复制代码

第八题:

  1. for (( i=1; i<9; i++))
  2. do
  3.         [[ $i -ne 8 ]] && let "j = $i + 2"
  4.         echo $(seq $i $j)
  5. done
复制代码

第九题:

  1. #!/bin/bash
  2. RESULT=./change_oracle_password_`date +%Y%m%d`
  3. > ${RESULT}
  4. echo -e "HOST\tRESULT\tNEW_PASSWORD" >> ${RESULT}

  5. for i in {1..1000}
  6. do
  7.         host=client$(printf "%04d\n" $i)
  8.         password=$(tr -dc 'A-Za-z0-9' < /dev/urandom | fold -w 8 |grep .*[0-9].*  -|grep .*[A-Z].* -|grep .*[a-z].* -|head -n 1)
  9.         ssh $host "echo "$password" | /usr/bin/passwd --stdin oracle"
  10.         if [ $? -eq 0];then
  11.                 echo -e "$host\tsuccess\t$password" >> ${RESULT}
  12.         else
  13.                 echo -e "$host\tfailed" >> ${RESULT}
  14.         fi        
  15. done
复制代码

第十题:

  1. #!/bin/bash
  2. #以下oracel相关部分google搜来,未测试
  3. export ORACLE_HOME=/path/to/oracle/
  4. export ORACLE_SID=...
  5. export PATH=$ORACLE_HOME/bin:$PATH

  6. sqlplus -silent <<SQLScript
  7. myuser/mypass
  8. set pages 0
  9. set feedback off
  10. set echo off
  11. spool ./dump_employee1_id
  12. select id from employee1
  13. spool off
  14. SQLScript

  15. sqlplus -silent <<SQLScript
  16. myuser/mypass
  17. set pages 0
  18. set feedback off
  19. set echo off
  20. spool ./dump_employee1_email
  21. select email from employee1
  22. spool off
  23. SQLScript

  24. mysql -u myuser -pmypass --batch -e 'select id from employee2' dbSecond | sed '1d' > dump_employee2_id
  25. mysql -u myuser -pmypass --batch -e 'select email from employee2' dbSecond | sed '1d' > dump_employee2_email

  26. for i in "dump_employee1_id" "dump_employee2_id" "dump_employee1_email" "dump_employee2_email"
  27. do
  28.         sort $i > ${i}_sort
  29. done

  30. comm -23 dump_employee1_id_sort dump_employee2_id_sort > different_id.txt
  31. comm -13 dump_employee1_id_sort dump_employee2_id_sort >> different_id.txt
  32. comm -23 dump_employee1_email_sort dump_employee2_email_sort > different_email.txt
  33. comm -13 dump_employee1_email_sort dump_employee2_email_sort >> different_email.txt
复制代码

最后谢谢各位评委。。。

论坛徽章:
0
发表于 2012-03-25 23:47 |显示全部楼层
第一题: 前两个作用一样,后面的awk -F '[ ]+'有区别,可匹配多个空格。

第二题: 两语句的功能一样。

第三题:echo {a,b,c,e,f}{1,2,3}

第四题:

第五题: $(<urfile)是命令替换,如用双引号括住,将原样输出,无法识别续行符。

第六题:因命令替换时,换行符检测不到,多个空格经处理,也会成一个空格。

第七题:

第八题:
#!/bin/bash.exe
declare -i j
declare -i i
for i in $(seq 7)
do
  j=$i+2
  seq -s " " $i $j
done
i=$i+1
echo $i $j

论坛徽章:
0
发表于 2012-03-25 23:51 |显示全部楼层

论坛徽章:
0
发表于 2012-03-28 17:26 |显示全部楼层
LZ 拿几个iphone,ipad出来多爽阿....

论坛徽章:
0
发表于 2012-03-28 17:43 |显示全部楼层
第三题:
如何用最简单的方法列举出 "a b c e f" 和"1 2 3" 的所有组合?

#!/bin/bash
###
for i in a b c e f
do

    for j in 1 2 3

    do
        echo $i $j

    done

done
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP