Chinaunix

标题: 下班了,周末给大家出个题目做做吧 [打印本页]

作者: cooljean2008    时间: 2009-03-06 18:04
标题: 下班了,周末给大家出个题目做做吧
老是写题目,下班了也给大家出个题目做做,周末一道小菜,呵呵~~
有文件file内容如下:
11

12

11



13
14
11

15


16
16

12


--------------------
file中包含了空行,空格,TAB,数字四种元素,其中数字可能重复出现,数字所在行之间的间隔不固定
要求:
将file中每2个相邻的数字为一行输出,对于重复的数字以第一次出现的位置为准
对于上例中,期望结果为:
11 12
13 14
15 16
并考虑奇数个数字的输出情况(最后一行不与提示符同行),即:
11 12
13
$
命令只能用awk来写,且不能用管道

明天来公布答案,不过我想应该等不到这个机会了

[ 本帖最后由 cooljean2008 于 2009-3-6 18:07 编辑 ]
作者: ly5066113    时间: 2009-03-06 18:09
标题: 回复 #1 cooljean2008 的帖子
awk '!/^[[:blank:]]*$/&&!a[$1]++{if(++i%2==0) print " "$1;else printf $1}END{if(i%2==1) print ""}' urfile

[ 本帖最后由 ly5066113 于 2009-3-6 18:11 编辑 ]
作者: 飞鸿无痕    时间: 2009-03-06 18:12
标题: 回复 #2 ly5066113 的帖子
感觉没什么问题能难住tim的,佩服!
作者: ztj2247    时间: 2009-03-06 18:37
原帖由 ly5066113 于 2009-3-6 18:09 发表
awk '!/^[[:blank:]]*$/&&!a[$1]++{if(++i%2==0) print " "$1;else printf $1}END{if(i%2==1) print ""}' urfile



每次看到TIM的回帖就感觉 他在坐F22 我还在学怎么爬。。。 相当纠结。。
作者: cinctum    时间: 2009-03-06 19:24
同样亚。
作者: merlin852    时间: 2009-03-06 19:36
tim下次低调点,给我们留点机会
作者: rhlei    时间: 2009-03-06 19:39
我怀疑Tim做题都不用测试。直接写。。。
作者: welcome008    时间: 2009-03-06 20:04
我没有看懂题目硬是

如果没有13该怎么样输出呢?
作者: ywlscpl    时间: 2009-03-06 20:14
  1. awk 'NF&&!a[$1]++{a[$1]=$1;n++;b[n]=$1}END{for(i=1;i<=n;i+=2)print b[i],b[i+1]}' file
复制代码

作者: oldoger    时间: 2009-03-06 22:02
标题: 回复 #8 welcome008 的帖子
没有13的话应该就是
11 12
14 15
16
这样输出吧
作者: dream3401    时间: 2009-03-06 22:06
awk '/[0-9]+/{a[i++]=$1}END{for(j=0;j<i;j+=2) print a[j],a[j+1]}' cfile
作者: linuxboy823    时间: 2009-03-07 00:56
原帖由 ly5066113 于 2009-3-6 18:09 发表
awk '!/^[[:blank:]]*$/&&!a[$1]++{if(++i%2==0) print " "$1;else printf $1}END{if(i%2==1) print ""}' urfile



TIM大哥

awk '!/^[[:blank:]]*$/&&!a[$1]++{if(++i%2==0) print " "$1;else printf $1}END{if(i%2==1) print ""}' urfile、、

红色部分如何理解,能否讲解一下,多谢!
作者: oldoger    时间: 2009-03-07 07:59
原帖由 linuxboy823 于 2009-3-7 00:56 发表



TIM大哥

awk '!/^[[:blank:]]*$/&&!a[$1]++{if(++i%2==0) print " "$1;else printf $1}END{if(i%2==1) print ""}' urfile、、

红色部分如何理解,能否讲解一下,多谢!

给你全例子吧,假如文件如下:
[test@ ~ ]$ cat 1
11

12

11



13
14
11

15


16
16

12
那么使用!a[$1]++得到的结果如下
[test@ ~ ]$ awk '!a[$1]++' 1
11

12
13
14
15
16
作者: linuxboy823    时间: 2009-03-07 11:50
原帖由 oldoger 于 2009-3-7 07:59 发表

给你全例子吧,假如文件如下:
[test@ ~ ]$ cat 1
11

12

11



13
14
11

15


16
16

12
那么使用!a[$1]++得到的结果如下
[test@ ~ ]$ awk '!a[$1]++' 1
11

12
13
14
15
16



那这个!是什么意思呢?!不是非的意思嘛?
作者: yingweixu    时间: 2009-03-07 11:58
[root@localhost test]# cat b.txt
11
12
11

13
14
11
15

16
16
12
awk 'BEGIN{num=1}$0!~/^$/{if(!a[$1]){b[num]=$1;num++;a[$1]=1}}END{for(s=1;s<=num;s+=2)print b" "b[s+1]}' b.txt

呵呵 我也贴个,就是长了点

[ 本帖最后由 yingweixu 于 2009-3-7 12:08 编辑 ]
作者: oldoger    时间: 2009-03-07 12:24
标题: 回复 #14 linuxboy823 的帖子
是表示非的意思,默认值为空或者0的时候不打印,其他值刚打印
作者: blackold    时间: 2009-03-07 12:27
弄个sed的:
  1. sed -r ':m;N;$!bm;${s/^\W+//;:n;s/((\<\w*\>).*)\<\2\>/\1/;tn;s/\W+/ /g;s/\<(\w+\> \<\w+)\> /\1\n/g;s/\W$//}' urfile
复制代码

  1. sed ':m;N;$!bm;${s/^\W\+//;:n;s/\(\(\<\w*\>\).*\)\<\2\>/\1/;tn;s/\W\+/ /g;s/\<\(\w\+\> \<\w\+\)\> /\1\n/g;s/\W$//}' urfile
复制代码


根据Tim的思路作了优化:
  1. sed -r ':n;$!{N;s/^\W+//;s/((\<\w*\>).*)\<\2\>/\1/;bn};s/\W+/ /g;s/\<(\w+\> \<\w+)\> /\1\n/g;s/\W$//' urfile
复制代码

  1. sed ':n;$!{N;s/^\W\+//;s/\(\(\<\w*\>\).*\)\<\2\>/\1/;bn};s/\W\+/ /g;s/\<\(\w\+\> \<\w\+\)\> /\1\n/g;s/\W$//' urfile
复制代码

[ 本帖最后由 blackold 于 2009-3-9 12:04 编辑 ]
作者: cooljean2008    时间: 2009-03-08 16:01
看了回复,大家真是神速!
也贴下我自己的答案吧:
awk '!a[$1]++&&NF{a[++i]=$1;if(i%2==0)print $1;else printf $1" "}END{if(i%2!=0)print " "}' file
作者: amwfnhz    时间: 2009-03-09 00:34
标题: 回复 #2 ly5066113 的帖子
大哥,你的[:blank:]是什么意思啊
作者: oldoger    时间: 2009-03-09 07:00
标题: 回复 #19 amwfnhz 的帖子
空格啊
作者: ly5066113    时间: 2009-03-09 10:23
标题: 回复 #17 blackold 的帖子
比黑哥的短一点。

  1. sed -r ':a;$!{N;s/\n\s*$//;s/(.*)(\<[0-9]+\>)(.*)\n\2/\1\2\3/;ba;};s/\n/ /;P;D' urfile
复制代码

作者: blackold    时间: 2009-03-09 10:37
原帖由 ly5066113 于 2009-3-9 10:23 发表
比黑哥的短一点。

sed -r ':a;$!{N;s/\n\s*$//;s/(.*)(\)(.*)\n\2/\1\2\3/;ba;};s/\n/ /;D' urfile


嗯,向Tim学习!
作者: blackold    时间: 2009-03-09 10:39
标题: 回复 #21 ly5066113 的帖子
输出不符合要求啊,我正在看……

Tim,s/(.*)(\<[0-9]+\>)(.*)\n\2/\1\2\3/这个有些问题,会把
16
1600中的一个干掉了。

[ 本帖最后由 blackold 于 2009-3-9 10:48 编辑 ]
作者: ly5066113    时间: 2009-03-09 11:04
标题: 回复 #23 blackold 的帖子
恩,谢谢黑哥提醒。后面也要加个单词边界:

  1. sed -r ':a;$!{N;s/\n\s*$//;s/(.*)(\<[0-9]+\>)(.*)\n\2\b/\1\2\3/;ba;};s/\n/ /;P;D' urfile
复制代码

作者: blackold    时间: 2009-03-09 11:49
标题: 回复 #24 ly5066113 的帖子
Tim, 不客气。

你的思路比我的好:读入一行就处理一行。学习!
作者: amwfnhz    时间: 2009-03-09 22:51
标题: 回复 #20 oldoger 的帖子
喔,谢谢。我没这样用过
作者: amwfnhz    时间: 2009-03-09 23:16
标题: 回复 #20 oldoger 的帖子
还有个,他[[:blank:]]中的两个[[是为什么呢,还有他后面*$是什么意思呢,是任意字符结尾的吗?请详细说明一下,我是新学的。谢谢

[ 本帖最后由 amwfnhz 于 2009-3-9 23:22 编辑 ]
作者: oldoger    时间: 2009-03-10 07:02
标题: 回复 #27 amwfnhz 的帖子
[[:blank:]]
[:blank:]这个才是表示空格的意思,就像你匹配a-z字母也要这样[a-z]
所以匹配空格也是要这样[[:blank:]]
*表示0个或者多个
$表示最后以空格结束。
!/^[[:blank:]]*$/
这样加起来就是排行了空行的情况。
作者: amwfnhz    时间: 2009-03-10 14:13
标题: 回复 #28 oldoger 的帖子
非常感谢大哥,懂了




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2