我有一个2N行的多列文件,它由0s,1s和缺失数据组成(编码为“?”)。它看起来像这样:
1 0 0 ? 1 ?
1 ? 1 ? 1 1
1 0 1 ? 1 1
0 ? 0 1 0 ?
0 0 1 ? 0 0
0 0 0 ? 0 ?
0 ? 0 0 1 1
1 1 1 1 1 1
我想总结每两行并输出一个N行文件。如果有“?”连续输出应该是“?”对于该特定字段(?+0 =?+ 1 =?+?=?)。所以我的例子的输出将如下所示:
2 ? 1 ? 2 ?
1 ? 1 ? 1 ?
0 0 1 ? 0 ?
1 ? 1 1 2 2
我尝试了这段代码,但似乎在计算时将丢失的数据视为“0”。有没有办法将丢失的数据保持为“?” ?
cat <input_file> |awk -F ' ' '{if (NR%2==1){for(j=1;j<=NF;j++)array[j]=$j;}else{result="";for(i=1;i<=NF;i++){tmp=array[i]+$i;result=sprintf("%s%d ",result,tmp);}print result;}}' > <output_file>
请帮忙。任何建议将不胜感激!
答案 0 :(得分:3)
我担心您必须将每个字段与"?"
进行比较:
< input_file awk '
NR%2 { split($0,saved,FS) } # save odd line fields
NR%2 == 0 { # on even lines:
for(i=1; i<=NF; i++){
$i = $i=="?" ? "?" : # "?" if this line field is "?"
saved[i]=="?" ? "?" : # "?" if the previous line field was "?"
saved[i]+$i # the sum otherwise
}
print
}'
答案 1 :(得分:3)
只能在一个(bash)shell中完成:
while read line; do
set -- $line
read line
ary=( $line )
i=0
for arg; do
if [ "$arg" = "?" -o "${ary[i]}" = "?" ]; then
printf "? "
else
printf "%d " $(( $arg + ${ary[i]} ))
fi
((i++))
done
printf "\n"
done < file
用awk,我写了类似的东西
awk '{
getline nextline
split(nextline, ary)
for (i=1; i<=NF; i++) {
if ($i == "?" || ary[i] == "?")
printf("? ")
else
printf("%d ", $i + ary[i])
}
print ""
}' file
答案 2 :(得分:1)
> cat temp.awk
{
if(NR%2==1)
{
split($0,a," ");
}
else
{
line="";
for(i=1;i<=NF;i++)
{
a[i]=="?"||$i=="?" ? sum="?":sum=a[i]+$i;
line=line" "sum;
}
print line;
}
}
创建上面的awk脚本后,使用以下命令:
awk -f temp.awk your_file
测试如下:
> awk -f temp.awk temp
2 ? 1 ? 2 ?
1 ? 1 ? 1 ?
0 0 1 ? 0 ?
1 ? 1 1 2 2