关键词重复行格式化输出问题

sh/bash/dash/ksh/zsh等Shell脚本
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

关键词重复行格式化输出问题

#1

帖子 fzfh » 2012-01-30 16:11

有一个文本文件,样式如下:
tab1 tab2 tab3
aa ee 11
bb ff 22
cc gg 33
dd hh 55
aa ee 77
bb ff 11
cc gg 88
dd hh 33
以第三列内容为关键词,分离出关键词重复的行;
上面的例子,有11,33两个关键词有重复行;
关键词重复行11内容为:
aa ee 11
bb ff 11
和关键词重复行33内容为:
cc gg 33
dd hh 33
然后输出2个文本,11和33
11的格式为:
aa-bb
ee-ff
33的格式为:
cc-dd
gg-hh

如果用awk或者sek的话,该如何写代码?
非常感谢!
同时预祝大伙灯节愉快,欢乐吉祥。
tusooa
帖子: 6548
注册时间: 2008-10-31 22:12
系统: 践兔
联系:

Re: 关键词重复行格式化输出问题

#2

帖子 tusooa » 2012-01-30 17:00

完全不需要awk,sed
[bash]declare -A hash
while read a b c; do
if [[ ${hash[$c]} == 1 ]] ; then
echo "$a-$b" >> "$c"
elif [[ ${hash[$c]} ]] ; then
echo "${hash[$c]}" > "$c"
echo "$a-$b" >> "$c"
hash[$c]=1
else
hash[$c]="$a-$b"
fi
done[/bash]

代码: 全选

] ls -ld //
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

Re: 关键词重复行格式化输出问题

#3

帖子 fzfh » 2012-01-30 17:29

对于多行多列,任意列为关键词呢?
头像
josephyoung
帖子: 158
注册时间: 2011-11-05 18:53
来自: 南极圈

Re: 关键词重复行格式化输出问题

#4

帖子 josephyoung » 2012-01-30 17:44

代码: 全选

awk '!a[$3]{a[$3]=$1"\n"$2;nlen=nlen<length(a[$3])?length(a[$3]):nlen;next}{sub("\n","-"$1"\n",a[$3]);sub("$","-"$2,a[$3])}END{for(i in a)if(length(a[i])>nlen)print a[i] > i}' file
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

Re: 关键词重复行格式化输出问题

#5

帖子 fzfh » 2012-01-30 18:19

楼上的对原始文本三列有效。如果是更多列呢?是不是需要加更多的sub?
能不能用循环呢?
头像
josephyoung
帖子: 158
注册时间: 2011-11-05 18:53
来自: 南极圈

Re: 关键词重复行格式化输出问题

#6

帖子 josephyoung » 2012-01-30 19:18

代码: 全选

awk 'NR==1{L=NF}{b[$NF]++;for(i=1;i<NF;i++)a[i,$NF]=a[i,$NF]?a[i,$NF]"-"$i:$i}END{for(i=1;i<L;i++)for(j in b)if(b[j]>1)print a[i,j]>j}' file
头像
eexpress
帖子: 58428
注册时间: 2005-08-14 21:55
来自: 长沙

Re: 关键词重复行格式化输出问题

#7

帖子 eexpress » 2012-01-30 19:38

不是有 uniq
● 鸣学
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

Re: 关键词重复行格式化输出问题

#8

帖子 fzfh » 2012-01-30 23:48

6楼的代码起作用了。
但是逻辑我不是理解不是很清楚。
看起来应该是以最后一列为关键词进行判断。
如果实际需求不是按最后一列为关键词进行判断的话,能不能在代码中增加一个变量来制定以那一列为关键词进行判断?
头像
josephyoung
帖子: 158
注册时间: 2011-11-05 18:53
来自: 南极圈

Re: 关键词重复行格式化输出问题

#9

帖子 josephyoung » 2012-01-31 0:28

更改"key"的值就是了

代码: 全选

awk -vkey=3 'NR==1{L=NF}{b[$key]++;for(i=1;i<=NF;i++)if(i!=key)a[i,$key]=a[i,$key]?a[i,$key]"-"$i:$i}END{for(i=1;i<=L;i++)for(j in b)if(b[j]>1 && i!=key)print a[i,j]}'
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

Re: 关键词重复行格式化输出问题

#10

帖子 fzfh » 2012-01-31 1:39

josephyoung 写了:更改"key"的值就是了

代码: 全选

awk -vkey=3 'NR==1{L=NF}{b[$key]++;for(i=1;i<=NF;i++)if(i!=key)a[i,$key]=a[i,$key]?a[i,$key]"-"$i:$i}END{for(i=1;i<=L;i++)for(j in b)if(b[j]>1 && i!=key)print a[i,j]}'
:em11 非常感谢。
fzfh
帖子: 31
注册时间: 2008-08-01 21:29
联系:

Re: 关键词重复行格式化输出问题

#11

帖子 fzfh » 2012-02-02 17:56

josephyoung 写了:更改"key"的值就是了

代码: 全选

awk -vkey=3 'NR==1{L=NF}{b[$key]++;for(i=1;i<=NF;i++)if(i!=key)a[i,$key]=a[i,$key]?a[i,$key]"-"$i:$i}END{for(i=1;i<=L;i++)for(j in b)if(b[j]>1 && i!=key)print a[i,j]}'
发现一个新问题,当行数超过1200行以后,这个代码如果在print后面用>j来输出文件的话就会出错。
错误提示:fatal: expression for `>' redirection has null string value
fnan
帖子: 919
注册时间: 2009-07-01 22:04

Re: 关键词重复行格式化输出问题

#12

帖子 fnan » 2012-02-04 21:32

awk打开文件不会自动关闭,数量有限制,要用close函数关闭,直接用shell处理更方便。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
fnan
帖子: 919
注册时间: 2009-07-01 22:04

Re: 关键词重复行格式化输出问题

#13

帖子 fnan » 2012-02-05 20:38

declare -A a=();key=3;while read l;do set $l;for ((n=1;n<=$#;n++));do [[ $n -ne $key ]] && a[${!key}-$n]=${a[${!key}-$n]}-${!n};done;done <file;for i in ${!a[*]};do [[ ${a[$i]} == ""-*-*"" ]] && echo ${a[$i]/-/} ${i/-*/};done
#没加空行处理。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
头像
josephyoung
帖子: 158
注册时间: 2011-11-05 18:53
来自: 南极圈

Re: 关键词重复行格式化输出问题

#14

帖子 josephyoung » 2012-02-06 19:52

多谢fnan指出这个问题,这样改不知道可以不可以

代码: 全选

awk -vkey=3 'NR==1{L=NF}{b[$key]++;for(i=1;i<=NF;i++)if(i!=key)a[i,$key]=a[i,$key]?a[i,$key]"-"$i:$i}END{for(i=1;i<=L;i++)for(j in b){if(b[j]>1 && i!=key)print a[i,j]>j;close(j)}}'
fnan
帖子: 919
注册时间: 2009-07-01 22:04

Re: 关键词重复行格式化输出问题

#15

帖子 fnan » 2012-02-07 4:49

josephyoung 写了:多谢fnan指出这个问题,这样改不知道可以不可以

代码: 全选

awk -vkey=3 'NR==1{L=NF}{b[$key]++;for(i=1;i<=NF;i++)if(i!=key)a[i,$key]=a[i,$key]?a[i,$key]"-"$i:$i}END{for(i=1;i<=L;i++)for(j in b){if(b[j]>1 && i!=key)print a[i,j]>j;close(j)}}'
#还差一点,试试看。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
回复