我有一个包含以下数据的文件-
输入-

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。基本上,我试图找出任何一行与第一行有多相似。
期望输出-
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。其他几排依次类推。
我已经编写了以下代码来完成这个转换-
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矩阵,这个程序在上面运行大约需要2个小时。
我希望你能帮我摆脱内环,这样我就可以一步完成所有6个GSUB。也许把它们放在自己的阵列中?我的技能还没那么好。

最佳答案

输入

$ 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
$ 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读取当前文件的第一条记录时,在大括号内执行操作
拆分(字符串,数组[,fieldsep[,seps]])
将字符串分割成由fieldsep分隔的片段并存储这些片段
以及seps数组中的分隔字符串。
split($0,a)
按fieldsep(defualt space,as)将当前记录或行($0)拆分为多个片段
我们没有提供第三个参数)并将这些片段存储在数组中a
所以数组包含第一行的数据
       a[1] = A
       a[2] = B
       a[3] = C
       a[4] = D
       a[5] = E
       a[6] = F

a
循环遍历每个文件记录的所有字段,直到文件结束。
for(i=1;i<=NF;i++)
如果当前索引(if (a[i]==$i) $i=1)的第一行列值等于
当前行的当前列值设置当前列值=1(表示修改当前列值)
现在我们修改了列值接下来只打印修改的行
i
}1始终计算为true,它执行默认操作1
关于评论的更新请求
同样的问题,我有程序的第二部分
行中的数字。也就是说,你可以得到6,2,4,2,2,3
输出。你的程序能不能调整一下,让这些值在这个
单步走?
$ 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

10-05 18:41