Awk 替换几列中大于数字的数字

Awk 替换几列中大于数字的数字,awk,Awk,我想用awk在我的矩阵中逐个替换那些大于1的数字(将0保留为0)。我的电脑正在使用: awk '$2>1 {$2=1} 1' 但是,我找不到选择多个列的方法(我有30个)。 如果我能避免替换标题的字符,那就太好了。 例如,如果我的表是: Species Sample_1 Sample_2 Sample_3 Species_1 15 4 0 Species_2 10 3 2 我想获得: Species Sample_1 Sa

我想用awk在我的矩阵中逐个替换那些大于1的数字(将0保留为0)。我的电脑正在使用:

awk '$2>1 {$2=1} 1'
但是,我找不到选择多个列的方法(我有30个)。 如果我能避免替换标题的字符,那就太好了。 例如,如果我的表是:

Species  Sample_1 Sample_2 Sample_3
Species_1   15      4         0
Species_2   10      3         2
我想获得:

Species  Sample_1 Sample_2 Sample_3
Species_1   1      1         0
Species_2   1      1         1
路易斯

awk'{
如果(NR>1){
对于(C=2;c1){$C=1}
}
}
打印
}'
awk'{
如果(NR>1){
对于(C=2;c1){$C=1}
}
}
打印
}'
$awk'
NR>1{
对于(i=2;i 1?1:$i)
}
}
1'文件|列-t
物种样本1样本2样本3
物种_1 0
种类2 1
$awk'
NR>1{
对于(i=2;i 1?1:$i)
}
}
1'文件|列-t
物种样本1样本2样本3
物种_1 0
种类2 1

sed的方法是

sed -E '2,${s/ 1?[2-9]+/ 1/g;s/ 1[0-9]+/ 1/g}' case_file_48228498 | column -t
Species    Sample_1  Sample_2  Sample_3
Species_1  1         1         0
Species_2  1         1         1

编辑1

我对上面的脚本进行了一些修改,以包括评论中建议/发现的角落案例。测试输入包含空格和制表符,用于分隔输入:

# cat case_file_48228498
Species    Sample_1   Sample_2      Sample_3
Species_1   1501      400000         010101
Species_2   10002     00400         00000 
Species_3   20000     100001        000000100044
下面是我修改过的脚本

# sed -E '2,${s/\s0+([1-9]+)/ \1/;s/\s1?[2-9]+/ 1/g;s/\s([0-1])[0-9]+/ \1/g}'  case_file_48228498 | column -t
Species    Sample_1  Sample_2  Sample_3
Species_1  1         1         1
Species_2  1         1         0
Species_3  1         1         1


注意:确实,上面所显示的是一种过度杀伤力。但还有更多。正如在的中所建议的那样,正则表达式不能代替数字比较,因为失败的情况不是立即可见的。

执行此操作的
sed
方法是

sed -E '2,${s/ 1?[2-9]+/ 1/g;s/ 1[0-9]+/ 1/g}' case_file_48228498 | column -t
Species    Sample_1  Sample_2  Sample_3
Species_1  1         1         0
Species_2  1         1         1

编辑1

我对上面的脚本进行了一些修改,以包括评论中建议/发现的角落案例。测试输入包含空格和制表符,用于分隔输入:

# cat case_file_48228498
Species    Sample_1   Sample_2      Sample_3
Species_1   1501      400000         010101
Species_2   10002     00400         00000 
Species_3   20000     100001        000000100044
下面是我修改过的脚本

# sed -E '2,${s/\s0+([1-9]+)/ \1/;s/\s1?[2-9]+/ 1/g;s/\s([0-1])[0-9]+/ \1/g}'  case_file_48228498 | column -t
Species    Sample_1  Sample_2  Sample_3
Species_1  1         1         1
Species_2  1         1         0
Species_3  1         1         1


注意:确实,上面所显示的是一种过度杀伤力。但还有更多。正如在’s中所建议的那样,正则表达式不能代替数值比较,因为失败案例并不立即可见。

I在实现三元运算符的类似行中进行了描述。手感不错。但是,
列-t
不是必需的。谢谢。是否需要
column-t
,取决于OP是否真的希望获得像她发布的示例输出中那样的列输出。她要的,所以她得到了…我在用类似的行写,实现了三元运算符。手感不错。但是,
列-t
不是必需的。谢谢。是否需要
column-t
,取决于OP是否真的希望获得像她发布的示例输出中那样的列输出。她要求它,所以她得到了它…对于各种输入值,它都会失败,例如,它会将
21
转换为
11
。最好不要尝试与regexp进行数字比较,因为通常会有边缘情况失败,只需坚持实际的数字比较(这意味着不要使用sed,因为它不支持数字比较)。@EdMorton谢谢。我为你指出的案子做了变通。。原则上我完全同意你的建议。尽管用户输入不可信,但我真的希望没有像
011
这样的值会失败。你也必须希望没有像102、1002、10002或100002这样的值会被12所取代。@GerardH.Pille欣赏这种讽刺的眼神。我想我也解决了这个问题。请参见编辑按钮。;-)@Pille只是证明当前输入文件中没有任何内容会导致未命中,但并不能证明没有任何值会导致未命中。我真的不知道是否还有其他情况它不能正确处理,但我绝对不会用它来做任何我真正关心的事情,因为我不能明确地说它能正确处理每一个情况,并且有更简单、更健壮、更便携的替代品!对于各种输入值,这将失败,例如,它将
21
转换为
11
。最好不要尝试与regexp进行数字比较,因为通常会有边缘情况失败,只需坚持实际的数字比较(这意味着不要使用sed,因为它不支持数字比较)。@EdMorton谢谢。我为你指出的案子做了变通。。原则上我完全同意你的建议。尽管用户输入不可信,但我真的希望没有像
011
这样的值会失败。你也必须希望没有像102、1002、10002或100002这样的值会被12所取代。@GerardH.Pille欣赏这种讽刺的眼神。我想我也解决了这个问题。请参见编辑按钮。;-)@Pille只是证明当前输入文件中没有任何内容会导致未命中,但并不能证明没有任何值会导致未命中。我真的不知道是否还有其他情况它不能正确处理,但我绝对不会用它来做任何我真正关心的事情,因为我不能明确地说它能正确处理每一个情况,并且有更简单、更健壮、更便携的替代品!