BASH - 使用 for 循环和 If 语句将第 2 列中的信息更改为 2

BASH - Change information in columns 2 by 2 using for loop and If statements

我有以下制表符分隔的文件:

A1    A1    0       0       1       1       0 0     0 0     2 2     1 2
A2    A2    0       0       1       1       1 1     1 1     0 0     1 2
A3    A3    0       0       1       2       1 1     1 1     0 0     2 2
A4    A4    0       0       1       1       1 1     0 0     0 0     1 2

想法是修改第 7 列(包括)和末尾之间的信息,对于每一行,如果第 7 列和第 8 列:

以下各列(第 9 和 10,然后是 11 和 12、13 和 14,等等)也是如此。

我开始使用以下命令提取我想要处理的列:

awk '{for (i = 7; i <= NF; i++) printf $i " "; print ""}' test.ped > tmp_test.txt

然后我想在 If 语句中使用 for 循环,一般格式为:

for i between 7 and the end (for (i = 7; i <= NF)):
    if i and i+1 == “1 2”:
        replace by “2 2”
    elif i and i+1 == “2 1”:
        replace by “2 2”
    else
        pass
    i=i+2 (increase i to do the same for the next double columns)

但是我被困在这里了。一般格式是否合乎逻辑,或者是否有更快的方法来做同样的事情?我正朝着正确的方向前进吗?

预期输出(在合并初始文件的前 6 列和我子集化和修改的列之后)是:

A1    A1    0       0       1       1       0 0     0 0     2 2     2 2
A2    A2    0       0       1       1       1 1     1 1     0 0     2 2
A3    A3    0       0       1       2       1 1     1 1     0 0     2 2
A4    A4    0       0       1       1       1 1     0 0     0 0     2 2

感谢您的帮助!

$ awk '{=;for(i=7;i<=NF;i+=2) if($i""$(i+1)=="1""2" || $i""$(i+1)=="2""1") {$i=2;$(i+1)=2} print}' test
A1 A1 0 0 1 1 0 0 0 0 2 2 2 2
A2 A2 0 0 1 1 1 1 1 1 0 0 2 2
A3 A3 0 0 1 2 1 1 1 1 0 0 2 2
A4 A4 0 0 1 1 1 1 0 0 0 0 2 2

.

{
    =                 # break the record (for even output)
    for(i=7;i<=NF;i+=2)   # the loop increase by 2s
        if($i""$(i+1)=="1""2" || $i""$(i+1)=="2""1") {
            $i=2;$(i+1)=2 # reset col values if 1,2 OR 2,1
        } 
    print                 # print record, changed or not
}

Awk是你的朋友。

awk -v FS='\t' -v OFS='\t' '{for(i=7;i<=NF;i++) \
 {if($i ~ /^[ 2]*[1]{1}[ 2]*$/){$i="2 2"}}}1'  file

应该做。

从您的问题来看,以下几对列似乎是 space 分开的(第 7 和第 8)、(第 9 和 10)、(第 11 和第 12)、(第 13 和第 14)。其他的是制表符分隔的。如果是这样的话,你可以不用循环就可以做到。

awk '{sub("1 2","2 2",[=10=]);sub("2 1","2 2",[=10=]); print;}' <filename>

听起来你只需要:

$ awk '{gsub(/1 2|2 1/,"2 2")}1' file
A1      A1      0       0       1       1       0 0     0 0     2 2     2 2
A2      A2      0       0       1       1       1 1     1 1     0 0     2 2
A3      A3      0       0       1       2       1 1     1 1     0 0     2 2
A4      A4      0       0       1       1       1 1     0 0     0 0     2 2

但是您的示例 input/output 确实无法帮助证明您的文字描述的内容,而且我认为您的字段并不像您所说的那样全部采用制表符分隔,所以这只是猜测。