Chinaunix

标题: linux下批量替换的问题 [打印本页]

作者: ilovefushun    时间: 2017-09-21 12:28
标题: linux下批量替换的问题
有一个数据文件a:
# 990430_232320 000210_132231 0.0
YOS -0.22000003
YUL 0.079999924
# 990501_000720 000210_132231 0.0
LIJ -0.080000043
YUL 0.12 1 P
# 990707_214529 000210_132231 0.0
YOS 0.059999943
# 990907_090133 000210_132231 0.0
BAS 0.38 1 P
# 991027_211412 000210_132231 0.0
HEQ -0.65999997


其中#后的两列为ID(旧),此外还有一ID列表b,第一列为旧的ID,第二列为新的ID:
000210_132231 1001
990430_232320 1002
990501_000720 1003
990707_214529 1004
990907_090133 1005
991027_211412  1006
现在想把a中的所有旧ID替换成新的ID,生成文件c:
# 1002 1001 0.0
YOS -0.22000003
YUL 0.079999924
# 1003 1001 0.0
LIJ -0.080000043
YUL 0.12 1 P
# 1004 1001 0.0
YOS 0.059999943
# 1005 1001 0.0
BAS 0.38 1 P
# 1006 1001 0.0
HEQ -0.65999997


我之前用sed一个一个替换,但是由于数据太多,执行效率太低了,后来用awk的双文件处理,但是执行过程中会出错,命令如下:
awk 'NR==FNR{a[$1]=$2;next}NR>FNR{if($2 in a)print $1,a[$1],$3,$4;else print $0}' b a > temp
awk 'NR==FNR{a[$1]=$2;next}NR>FNR{if($3 in a)print $1,$2,a[$1],$4;else print $0}' b temp > c

请问是哪里出错了,应该怎样做,谢谢!
作者: jason680    时间: 2017-09-21 12:41
回复 1# ilovefushun

$ awk 'FNR==NR{a[$1]=$2;next}/^#/{for(n=2;n<NF;++n)if($n in a)$n=a[$n]}1' b a > c

$ cat c
# 1002 1001 0.0
YOS -0.22000003
YUL 0.079999924
# 1003 1001 0.0
LIJ -0.080000043
YUL 0.12 1 P
# 1004 1001 0.0
YOS 0.059999943
# 1005 1001 0.0
BAS 0.38 1 P
# 1006 1001 0.0
HEQ -0.65999997


作者: ilovefushun    时间: 2017-09-21 13:06
回复 2# jason680

可以了,谢谢!
作者: sunzhiguolu    时间: 2017-09-21 13:21
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;

  4. my $keys = {};
  5. while(<DATA>){
  6.         last if(/\A\s*\z/);
  7.         my ($old, $new) = split;
  8.         $keys->{$old} = $new;
  9. }

  10. while(<DATA>){
  11.         if(!/\A#/){
  12.                 print;
  13.                 next;
  14.         }
  15.         foreach my $id (grep {exists($keys->{$_})} (split)[1, 2]){
  16.                 s/$id/$keys->{$id}/;
  17.         }
  18.         print;
  19. }

  20. __DATA__
  21. 000210_132231 1001
  22. 990430_232320 1002
  23. 990501_000720 1003
  24. 990707_214529 1004
  25. 990907_090133 1005
  26. 991027_211412  1006

  27. # 990430_232320 000210_132231 0.0
  28. YOS -0.22000003
  29. YUL 0.079999924
  30. # 990501_000720 000210_132231 0.0
  31. LIJ -0.080000043
  32. YUL 0.12 1 P
  33. # 990707_214529 000210_132231 0.0
  34. YOS 0.059999943
  35. # 990907_090133 000210_132231 0.0
  36. BAS 0.38 1 P
  37. # 991027_211412 000210_132231 0.0
  38. HEQ -0.65999997
复制代码

作者: 龙牙地主天    时间: 2017-09-21 14:14
本帖最后由 龙牙地主天 于 2017-09-21 14:23 编辑
  1. awk 'NR==FNR{a[$1]=$2 ; next}/^#/{for(i in a) {if($2==i) $2=a[$2] ; if($3==i) $3=a[$3]}}1' b a
复制代码

  1. awk 'NR==FNR{a[$1]=$2 ; next}/^#/{for(i in a) {if($2==i) $2=a[$2] ; if($3==i) $3=a[$3]}}{print > "c"}' b a
复制代码

作者: wh7211    时间: 2017-09-21 14:17
本帖最后由 wh7211 于 2017-09-21 14:22 编辑

回复 1# ilovefushun


  1. awk 'NR==FNR{a[$1]=$2;next}/^#/{$2=$2 in a?a[$2]:$2;$3=$3 in a?a[$3]:$3}{print>"c"}' b a
复制代码

作者: 本友会机友会摄友会    时间: 2017-09-21 15:10
提示: 作者被禁止或删除 内容自动屏蔽
作者: ilovefushun    时间: 2017-09-21 15:49
本帖最后由 ilovefushun 于 2017-09-21 16:00 编辑

回复 2# jason680

不好意思,还有一个问题。if($2 in a),表示如果$2的值在数组a中,则执行后面的命令,我想问一下如果$2的值不在数组a中应该怎么写?if(! $2 in a),if !($2 in a),!(if($2 in a)),这几种写法都试了,但是都运行不了
作者: jason680    时间: 2017-09-21 16:02
本帖最后由 jason680 于 2017-09-21 16:05 编辑

回复 8# ilovefushun

$ echo 1 2 3 4 x y z| awk 'BEGIN{a[1]=a[4]=a["y"]=1}{for(n=1;n<=NF;++n)if($n in a)print $n}'
1
4
y

$ echo 1 2 3 4 x y z| awk 'BEGIN{a[1]=a[4]=a["y"]=1}{for(n=1;n<=NF;++n)if(!($n in a))print $n}'
2
3
x
z

$ echo 1 2 3 4 x y z| awk 'BEGIN{a[1]=a[4]=a["y"]=1}{for(n=1;n<=NF;++n)if($n in a)print "yes:"$n;else print "no:"$n}'
yes:1
no:2
no:3
yes:4
no:x
yes:y
no:z


作者: ilovefushun    时间: 2017-09-21 16:04
回复 9# jason680

哦,知道了,谢谢您!
作者: chengchow    时间: 2017-09-21 20:19
  1. [root@iZuf62sazcxqandkv55wyjZ tmp]# awk 'NR==FNR{a[$1]=$2}NR!=FNR{if($1=="#"){$2=a[$2];$3=a[$3]};print}' b a
  2. # 1002 1001 0.0
  3. YOS -0.22000003
  4. YUL 0.079999924
  5. # 1003 1001 0.0
  6. LIJ -0.080000043
  7. YUL 0.12 1 P
  8. # 1004 1001 0.0
  9. YOS 0.059999943
  10. # 1005 1001 0.0
  11. BAS 0.38 1 P
  12. # 1006 1001 0.0
  13. HEQ -0.65999997
复制代码

作者: wh7211    时间: 2017-09-22 14:54
回复 11# chengchow

这段代码有个限制条件,就是文件a中的id必须全部都在文件b中出现,否则a中的、未在文件b中出现的id会被替换成空值。




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