从awk中的多个特定列中减去单个最大数
Subtract single largest number from multiple specific columns in awk
我有一个逗号分隔的文件,看起来像
R,F,TE,K,G,R
1,0,12,f,1,18
2,1,17,t, ,17
3,1, , ,1,
4,0,15, ,0,16
有些项目丢失了,第一行也是我想忽略的 header。我想计算特定列中第二小的数字,并从该列中的所有元素中减去它,除非该列中的值是最小值。在此示例中,我想从示例中的第 3 列和第 6 列中减去第二个最小值。所以,我的最终值是:
R,F,TE,K,G,R
1,0,12,f,1,1
2,1, 2,t, ,0
3,1, , ,0,
4,0, 0, ,0,16
我尝试单独使用单列并给出 hand-coded 阈值使其成为第二大
awk 'BEGIN {FS=OFS=",";
};
{ min=1000000;
if(<min && != "" && >12) min = ;
if(>0) = -min+1;
print}
END{print min}
' try1.txt
它找到了最小值,但输出不符合预期。 awk 中应该有更简单的方法。
BEGIN{
FS=OFS=","
}
{
if(NR==1){print;next}
if(+)a[NR]=
if(+)b[NR]=
s[NR]=[=10=]
}
END{
asort(a,c)
asort(b,d)
for(i=2;i<=NR;i++){
split(s[i],t)
if(t[3]!=c[1]&&+t[3]!=0)t[3]=t[3]-c[2]
if(t[6]!=d[1]&&+t[6]!=0)t[6]=t[6]-d[2]
print t[1],t[2],t[3],t[4],t[5],t[6]
}
}
我会遍历文件两次,一次是为了找到最小值,一次是为了调整值。这是时间与内存的权衡。
awk -F, -v OFS=, '
NR == 1 {min3 = ; min6 = }
NR == FNR {if ( < min3) min3 = ; if ( < min6) min6 = ; next}
!= min3 { -= min3}
!= min6 { -= min6}
{print}
' try1.txt try1.txt
为了更漂亮的输出:
awk -F, -v OFS=, '
NR == 1 {min3 = ; min6 = ; next}
NR == FNR {if ( < min3) min3 = ; if ( < min6) min6 = ; next}
FNR == 1 {len3 = length("" min3); len6 = length("" min6)}
!= min3 { = sprintf("%*d", len3, -min3)}
!= min6 { = sprintf("%*d", len6, -min6)}
{print}
' try1.txt try1.txt
鉴于新要求:
min2_3=$(cut -d, -f3 try1.txt | tail -n +2 | sort -n | grep -v '^ *$' | sed -n '2p')
min2_6=$(cut -d, -f6 try1.txt | tail -n +2 | sort -n | grep -v '^ *$' | sed -n '2p')
awk -F, -v OFS=, -v min2_3=$min2_3 -v min2_6=$min2_6 '
NR==1 {print; next}
!~ /^ *$/ && >= min2_3 { -= min2_3}
!~ /^ *$/ && >= min2_6 { -= min2_6}
{print}
' try1.txt
R,F,TE,K,G,R
1,0,12,f,1,1
2,1,2,t, ,0
3,1, , ,1,
4,0,0, ,0,16
我有一个逗号分隔的文件,看起来像
R,F,TE,K,G,R
1,0,12,f,1,18
2,1,17,t, ,17
3,1, , ,1,
4,0,15, ,0,16
有些项目丢失了,第一行也是我想忽略的 header。我想计算特定列中第二小的数字,并从该列中的所有元素中减去它,除非该列中的值是最小值。在此示例中,我想从示例中的第 3 列和第 6 列中减去第二个最小值。所以,我的最终值是:
R,F,TE,K,G,R
1,0,12,f,1,1
2,1, 2,t, ,0
3,1, , ,0,
4,0, 0, ,0,16
我尝试单独使用单列并给出 hand-coded 阈值使其成为第二大
awk 'BEGIN {FS=OFS=",";
};
{ min=1000000;
if(<min && != "" && >12) min = ;
if(>0) = -min+1;
print}
END{print min}
' try1.txt
它找到了最小值,但输出不符合预期。 awk 中应该有更简单的方法。
BEGIN{
FS=OFS=","
}
{
if(NR==1){print;next}
if(+)a[NR]=
if(+)b[NR]=
s[NR]=[=10=]
}
END{
asort(a,c)
asort(b,d)
for(i=2;i<=NR;i++){
split(s[i],t)
if(t[3]!=c[1]&&+t[3]!=0)t[3]=t[3]-c[2]
if(t[6]!=d[1]&&+t[6]!=0)t[6]=t[6]-d[2]
print t[1],t[2],t[3],t[4],t[5],t[6]
}
}
我会遍历文件两次,一次是为了找到最小值,一次是为了调整值。这是时间与内存的权衡。
awk -F, -v OFS=, '
NR == 1 {min3 = ; min6 = }
NR == FNR {if ( < min3) min3 = ; if ( < min6) min6 = ; next}
!= min3 { -= min3}
!= min6 { -= min6}
{print}
' try1.txt try1.txt
为了更漂亮的输出:
awk -F, -v OFS=, '
NR == 1 {min3 = ; min6 = ; next}
NR == FNR {if ( < min3) min3 = ; if ( < min6) min6 = ; next}
FNR == 1 {len3 = length("" min3); len6 = length("" min6)}
!= min3 { = sprintf("%*d", len3, -min3)}
!= min6 { = sprintf("%*d", len6, -min6)}
{print}
' try1.txt try1.txt
鉴于新要求:
min2_3=$(cut -d, -f3 try1.txt | tail -n +2 | sort -n | grep -v '^ *$' | sed -n '2p')
min2_6=$(cut -d, -f6 try1.txt | tail -n +2 | sort -n | grep -v '^ *$' | sed -n '2p')
awk -F, -v OFS=, -v min2_3=$min2_3 -v min2_6=$min2_6 '
NR==1 {print; next}
!~ /^ *$/ && >= min2_3 { -= min2_3}
!~ /^ *$/ && >= min2_6 { -= min2_6}
{print}
' try1.txt
R,F,TE,K,G,R
1,0,12,f,1,1
2,1,2,t, ,0
3,1, , ,1,
4,0,0, ,0,16