关键词重复行格式化输出问题
-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
关键词重复行格式化输出问题
有一个文本文件,样式如下:
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的话,该如何写代码?
非常感谢!
同时预祝大伙灯节愉快,欢乐吉祥。
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的话,该如何写代码?
非常感谢!
同时预祝大伙灯节愉快,欢乐吉祥。
-
- 帖子: 6548
- 注册时间: 2008-10-31 22:12
- 系统: 践兔
- 联系:
Re: 关键词重复行格式化输出问题
完全不需要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]
[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 //
-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
Re: 关键词重复行格式化输出问题
对于多行多列,任意列为关键词呢?
- josephyoung
- 帖子: 158
- 注册时间: 2011-11-05 18:53
- 来自: 南极圈
Re: 关键词重复行格式化输出问题
代码: 全选
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
-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
Re: 关键词重复行格式化输出问题
楼上的对原始文本三列有效。如果是更多列呢?是不是需要加更多的sub?
能不能用循环呢?
能不能用循环呢?
- josephyoung
- 帖子: 158
- 注册时间: 2011-11-05 18:53
- 来自: 南极圈
Re: 关键词重复行格式化输出问题
代码: 全选
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
- 来自: 长沙
-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
Re: 关键词重复行格式化输出问题
6楼的代码起作用了。
但是逻辑我不是理解不是很清楚。
看起来应该是以最后一列为关键词进行判断。
如果实际需求不是按最后一列为关键词进行判断的话,能不能在代码中增加一个变量来制定以那一列为关键词进行判断?
但是逻辑我不是理解不是很清楚。
看起来应该是以最后一列为关键词进行判断。
如果实际需求不是按最后一列为关键词进行判断的话,能不能在代码中增加一个变量来制定以那一列为关键词进行判断?
- josephyoung
- 帖子: 158
- 注册时间: 2011-11-05 18:53
- 来自: 南极圈
Re: 关键词重复行格式化输出问题
更改"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]}'
-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
Re: 关键词重复行格式化输出问题
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]}'

-
- 帖子: 31
- 注册时间: 2008-08-01 21:29
- 联系:
Re: 关键词重复行格式化输出问题
发现一个新问题,当行数超过1200行以后,这个代码如果在print后面用>j来输出文件的话就会出错。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]}'
错误提示:fatal: expression for `>' redirection has null string value
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 关键词重复行格式化输出问题
awk打开文件不会自动关闭,数量有限制,要用close函数关闭,直接用shell处理更方便。
bash不如perl精妙,学不到lisp的皮毛,远不够c++强悍,不过可以用。
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 关键词重复行格式化输出问题
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: 关键词重复行格式化输出问题
多谢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)}}'
-
- 帖子: 919
- 注册时间: 2009-07-01 22:04
Re: 关键词重复行格式化输出问题
#还差一点,试试看。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++强悍,不过可以用。