首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GSub多列同时基于不同的gsub条件?

GSub多列同时基于不同的gsub条件?
EN

Stack Overflow用户
提问于 2017-01-03 17:10:10
回答 2查看 117关注 0票数 4

我有一份有以下数据的文件-

投入-

代码语言:javascript
复制
A B C D E F
A B B B B B
C A C D E F
A B D E F A
A A A A A F
A B C B B B

如果从第2行开始的其他行与第1行有相同的字母,则应该将它们更改为1。基本上,我正在试图找出任何一行与第一行有多相似。

期望输出-

代码语言:javascript
复制
1 1 1 1 1 1
1 1 B B B B
C A 1 1 1 1
1 1 D E F A
1 A A A A 1
1 1 1 B B B

第一行已经成为全部1,因为它本身是相同的(很明显)。在第二行中,第一列和第二列与第一行(A B)相同,因此它们成为1 1。其他行也是如此。

我写了下面的代码来完成这个转换-

代码语言:javascript
复制
for seq in {1..1} ; #Iterate over the rows (in this case just row 1)
do 
    for position in {1..6} ; #Iterate over the columns
    do 
        #Define the letter in the first row with which I'm comparing the rest of the rows
        aa=$(awk -v pos=$position -v line=$seq 'NR == line {print $pos}' f) 
        #If it matches, gsub it to 1 
        awk -v var=$aa -v pos=$position '{gsub (var, "1", $pos)} 1' f > temp
        #Save this intermediate file and now act on this
        mv temp f 
    done 
done

可以想象,这非常慢,因为嵌套循环非常昂贵。我的真实数据是一个60x10000矩阵,这个程序需要大约两个小时才能在这个矩阵上运行。

我希望你能帮我摆脱内环,这样我就可以在一步内完成所有6个gsubs了。也许把他们放进自己的数组里?我的awk技能还没那么好。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-01-03 17:41:10

输入

代码语言:javascript
复制
$ cat f
A B C D E F
A B B B B B
C A C D E F
A B D E F A
A A A A A F
A B C B B B

所需的o/p

代码语言:javascript
复制
$ awk 'FNR==1{split($0,a)}{for(i=1;i<=NF;i++)if (a[i]==$i) $i=1}1' f
1 1 1 1 1 1
1 1 B B B B
C A 1 1 1 1
1 1 D E F A
1 A A A A 1
1 1 1 B B B

解释

  • FNR==1{ .. }

awk读取当前文件的第一次记录时,在大括号内执行操作

拆分(字符串、数组[、字段seps、seps ]) 将字符串划分为由字段seps分隔的部分,并将其存储在数组中,并将分隔字符串存储在seps数组中。

  • split($0,a)

将当前记录或行($0)按字段So (defualt,因为我们没有提供第3个参数)分割成块,并将这些片段存储在数组a中,因此数组a包含来自第一行的数据。

代码语言:javascript
复制
       a[1] = A 
       a[2] = B
       a[3] = C 
       a[4] = D  
       a[5] = E  
       a[6] = F
  • for(i=1;i<=NF;i++)

循环遍历每个文件记录的所有字段,直到文件结束。

  • if (a[i]==$i) $i=1

如果第一行的当前索引列值(i)等于当前行的当前列值,则设置当前列值=1(意思是修改当前列值)

现在我们修改了列值,然后只打印修改过的行

  • }1 1总是计算为true,它执行默认操作{print $0}

用于对注释的更新请求

同样的问题,我还有一个程序的第二部分,它将行中的数字相加。也就是说,这个输出可以得到6,2,4,2,2,3。您的程序是否可以在这一步中调整以获得这些值?

代码语言:javascript
复制
$ awk 'FNR==1{split($0,a)}{s=0;for(i=1;i<=NF;i++)if(a[i]==$i)s+=$i=1;print $0,s}' f
1 1 1 1 1 1 6
1 1 B B B B 2
C A 1 1 1 1 4
1 1 D E F A 2
1 A A A A 1 2
1 1 1 B B B 3
票数 3
EN

Stack Overflow用户

发布于 2017-01-03 17:24:53

您可以使用这个更简单的awk命令来完成这项工作,因为我们避免了shell中的嵌套循环,并且在嵌套循环中重复调用awk:

代码语言:javascript
复制
awk '{for (i=1; i<=NF; i++) {if (NR==1) a[i]=$i; if (a[i]==$i) $i=1} } 1' file

1 1 1 1 1 1
1 1 B B B B
C A 1 1 1 1
1 1 D E F A
1 A A A A 1
1 1 1 B B B

编辑:

如下面的注释所示,您可以做些什么来获得每一行中每列的和:

代码语言:javascript
复制
awk '{sum=0; for (i=1; i<=NF; i++) { if (NR==1) a[i]=$i; if (a[i]==$i) $i=1; sum+=$i}
      print $0, sum}' file

1 1 1 1 1 1 6
1 1 B B B B 2
C A 1 1 1 1 4
1 1 D E F A 2
1 A A A A 1 2
1 1 1 B B B 3
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41448772

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档