LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: jiazhengw

多发发一些有意思的题做做呀![+sed/awk/regex练习]

[复制链接]
发表于 2006-3-2 18:48:21 | 显示全部楼层
Post by shizi4838
我查了点资料,资料上说这是awk的一个缺点,当 awk 在数组下标之间轮转时,它不会依照任何特定的顺序。也就是说使用for (i in a) print i时,输出的结果是没有什么规律的,即便是从4开始的结论也应该是错误的,它只是用i把a中的值轮转一遍.


啊,不会吧,怎么象perl的HASH一样,呵呵,多谢了.
回复 支持 反对

使用道具 举报

发表于 2006-3-2 20:00:34 | 显示全部楼层
习题一: 文件一 first  文件二 second
我把我的程序改动了点,现在可以输出题目要求的结果了。

  1. more change.sh
  2. #!/bin/bash
  3. sed 's/^ *//g' second >sort      #去second行首空格>sort
  4. #把sort文件拆分到file1,file2,file3,file4四个文件中去,其中前三个文件最后一行为空行,
  5. #最后一个文件中没有空行。
  6. a=`more sort |wc -l`
  7. b=1
  8. j=1
  9. for((i=1; i<=$a; i++))
  10. do
  11. sed -n ''$i'p' sort> sort1
  12. string=`sed 's/^$//g' sort1`
  13. if [ -z  "$string" ];
  14. then
  15.     b=`expr $i - 1`
  16.     sed -n ''$b'p' sort> sort1
  17.     string=`sed 's/^$//g' sort1`
  18.     if [ ! -z  "$string" ];
  19.     then
  20.        echo -e "\n" >> file$j      
  21.      j=`expr $j + 1`
  22.     fi
  23. else
  24.    c=`sed -n ''$i'p' sort`
  25.    echo -n $c >> file$j
  26. fi
  27. done
  28. j=`expr $j - 1`
  29. sed  '/^$/d' file$j >trans
  30. cp trans file$j
  31. rm sort*
  32. #把first和second文件合并到third文件,third文件的内容即为要得到的结果。
  33. sed -n 's/.*/&:/p' first> third
  34. a=`more first |wc -l`
  35. for((i=$a; i>=1; i--))
  36. do
  37. sed ''$i' r file'$i'' third > trans
  38. cp trans third
  39. done
  40. #删除中间过度文件。
  41. rm file*
  42. rm trans
  43. more third
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-3-2 23:49:38 | 显示全部楼层
是,awk中array的历遍并不是按照index的值从小到大,实际上awk中的index没有大小,因为都是string.这是有点象hash. 而awk中对array的存储也很象hash,所以结果不是按“顺序”来的。
回复 支持 反对

使用道具 举报

发表于 2006-3-3 09:16:49 | 显示全部楼层
Post by yongjian

要求:
1. 用gawk来做(sed好象也做不了,呵呵)
2. Avg的计算结果保留两位小数,四舍五入。

我只是想知道,那些 12.03 + 11.04 是怎么相加的?expr 不支持的说。

sed做无非就是把相应的字段取出后,再运算,比较麻烦。也可以做的吧。:p
回复 支持 反对

使用道具 举报

发表于 2006-3-3 09:43:49 | 显示全部楼层
请教Johnny_jiang兄有关9楼10楼的两个程序:
两个程序我都把代码拷了下来放到本地机器上执行了一下,结果都有一个问题,就是程序执行完毕后不能输出shell符,即像
esxsuse2:/home#
这种样子,10楼的程序在我机器上运行也没有任何输出,我分析了一下,怀疑是两个程序执行到最后都陷入了死循环,问题应该出现在这句上:while ($0 == "") getline ,getline这个命令是不是不会判断已经到了文件的结尾,也就是说到了文件的最后一行,如果没有给出任何触发,它会一直getline最后一行,这也就陷入了死循环,这也就找到了10楼程序为什么没有任何输出的原因,因为END{}模式之前已经陷入了死循环,该模式中的语句根本没有执行.
我对getline的用法不了解,不知道在Johnny_jiang兄的机器上运行有没有和我一样的毛病,如果没有那就是我的shell有问题了.请Johnny_jiang指点一下.
回复 支持 反对

使用道具 举报

发表于 2006-3-3 10:46:12 | 显示全部楼层
Johnny_jiang兄,我把你9楼的程序改了一下,如下:

  1. #filename  sort.a
  2. #!/bin/awk -f
  3. BEGIN { getline title < "first"; print title":" }
  4. {
  5. if ($0 == "") {
  6. getline title < "first"
  7. print "\n\n"title":"
  8. #getline
  9. #while ($0 == "") getline
  10. }
  11. for (i=1;i<=NF;i++) printf "%s ",$i
  12. }
  13. END { print "" }
复制代码

又写了个去除重复空行的脚本,如下:

  1. #filename  sort.b
  2. #!/bin/awk -f
  3. BEGIN{line="null"}
  4. {if ($0=="" && line=="")
  5. next;
  6. line=$0;
  7. print}
复制代码

这样的话就可以了.在当前目录下使用以下命令:

  1. ./sort.b second |sed '$d' | ./sort.a
复制代码

呵呵,中间又用了个sed命令,删除最后一个空行.
回复 支持 反对

使用道具 举报

发表于 2006-3-3 12:07:46 | 显示全部楼层
Post by 终极幻想
我只是想知道,那些 12.03 + 11.04 是怎么相加的?expr 不支持的说。

sed做无非就是把相应的字段取出后,再运算,比较麻烦。也可以做的吧。:p

awk本身支持数学运算。但sed就不支持了,所以如果纯粹用sed是做不出来的。之所以规定编写工具主要是想练习其中的一些功能。
回复 支持 反对

使用道具 举报

发表于 2006-3-3 12:21:55 | 显示全部楼层
Post by shizi4838
Johnny_jiang兄,我把你9楼的程序改了一下,如下:

  1. #filename  sort.a
  2. #!/bin/awk -f
  3. BEGIN { getline title < "first"; print title":" }
  4. {
  5. if ($0 == "") {
  6. getline title < "first"
  7. print "\n\n"title":"
  8. #getline
  9. #while ($0 == "") getline
  10. }
  11. for (i=1;i<=NF;i++) printf "%s ",$i
  12. }
  13. END { print "" }
复制代码

又写了个去除重复空行的脚本,如下:

  1. #filename  sort.b
  2. #!/bin/awk -f
  3. BEGIN{line="null"}
  4. {if ($0=="" && line=="")
  5. next;
  6. line=$0;
  7. print}
复制代码

这样的话就可以了.在当前目录下使用以下命令:

  1. ./sort.a second |sed '$d' | ./sort.b
复制代码

呵呵,中间又用了个sed命令,删除最后一个空行.

运行了以下Johnny兄的程序,也出现了你说的问题。然后又将你改进的程序运行了一下,出现了这样的结果:

  1. ifconfig:
  2. The ifconfig command is used to configure the kernel-resident network interfaces. It is used at boot time to set up interfaces as necessary. After that, it is usually only needed when debugging or when system tuning is needed.

  3. shutdown:

  4. iptables:

  5. fdisk:
  6. shutdown command brings the system down in a secure way. All logged-in users are notified that the system is going down, and login(1) is blocked. It is possible to shut the system down immediately or after a specified delay.

  7. fdisk:

  8. fdisk:

  9. fdisk:

  10. fdisk:
  11. Iptables is used to set up, maintain, and inspect the tables of IP packet filter rules in the Linux kernel. Several different tables may be defined. Each table contains a number of built-in chains and may also contain user-defined chains.

  12. fdisk:

  13. fdisk:
  14. Hard disks can be divided into one or more logical disks called partitions. This division is described in the partition table found in sector 0 of the disk.

  15. fdisk:

  16. fdisk:

  17. fdisk:

  18. fdisk:
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-3-3 12:31:23 | 显示全部楼层
提醒一下,前面的习题一有新注释,主要是paste到网页上的时候第二个文件的最后的空行都没有了,请自己在末尾加上一些空行。
回复 支持 反对

使用道具 举报

发表于 2006-3-3 12:42:15 | 显示全部楼层
这是我做的习题一的代码,在自己的机子上运行结果正确,不过看来还得在其他人的机器上试试才行。
第一个文件叫cmd1,第二个文件叫cmd1_desc.
sed:
  1. for i in $(seq 1 $(wc -l cmd1|sed 's/\(^.*\) .*/\1/g')); do j=$(cat cmd1_desc | sed -n 'H;/^$/{x;s/\n/ /g;G;p;}'|sed '/^ $/d;/^$/d;s/ \+/ /g' | sed -n ''$i'p'); k=$(cat cmd1 | sed -n ''$i's/.*/&:/p' | sed '$a\'"$j"'');echo -e "$k\n" ;done | sed '$d'
复制代码
awk:
  1. awk 'BEGIN{FS="\n";RS=""};gsub(/\n/," ")' cmd1_desc| awk 'gsub(/ +/," ")' | awk 'getline cmd < "cmd1";{print cmd":"}' | awk '{if((getline tmp)>0){print tmp;print $0"\n"}}' | awk '{if(NR == 1){str=$0}else{print str;str=$0}}'
复制代码
回复 支持 反对

使用道具 举报

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

本版积分规则

快速回复 返回顶部 返回列表