awk添加可变数量的缺失值

时间:2016-05-16 16:59:09

标签: bash if-statement for-loop awk

我在第一列中有一组带有基因标识符的制表符分隔文件,每个后续列代表第一列中具有该给定基因值的单个样本。以下是我的一个文件的截断示例,只有少量示例:

DDR1 8.55578403700418 8.65526857898327 8.71701700266541 
MIR4640 8.55578403700418 8.65526857898327 8.71701700266541 
RFC2  5.47524925570941 5.88644077981836 5.77277342309348
HSPA6 4.12035662689116 4.01089068869244 3.82366440713502
PAX8  
GUCA1A   

我从Awk adding constant valuesBash Script Awk if statementsAWK if length statement append得到了一些想法,因为我根据输入文件有几千行甚至几百列,所以我尝试编写我的脚本这样:

cd ../path/to/file

inputFile=inputFile.in
outputFile=outputFile.out

columnCount= $(awk -F"\t" 'NR==1 {print NF}' $inputFile)

awk '{ for (i = 1; i <= $columnCount; i++)

    if (i<$columnCount) {print $0"\t?"}' $inputFile > $outputFile
}'

但我一直遇到语法错误。

$ awk -f missingValueAdder.awk 
awk: missingValueAdder.awk:3: cd ../path/to/file
awk: missingValueAdder.awk:3:    ^ syntax error
awk: missingValueAdder.awk:5: inputFile=inputFile.in
awk: missingValueAdder.awk:5:                    ^ syntax error
awk: missingValueAdder.awk:6: outputFile=outputFile.out
awk: missingValueAdder.awk:6                       ^ syntax error
awk: missingValueAdder.awk:8: columnCount= $(awk -F"\t" 'NR==1 {print NF}' $inputFile) 
awk: missingValueAdder.awk:8:                           ^ invalid char ''' in expression

所以我试过这个单行

 awk 'for (i=1;i<=NF;i++) BEGIN{FS=OFS="\t"} I<NF{print$0"\t?"}' inputFile.in > outputFile.out

但是我的for循环开始出现另一个语法错误。无论如何,我的输出文件应该看起来像

DDR1 8.55578403700418 8.65526857898327 8.71701700266541 
MIR4640 8.55578403700418 8.65526857898327 8.71701700266541 
RFC2  5.47524925570941 5.88644077981836 5.77277342309348
HSPA6 4.12035662689116 4.01089068869244 3.82366440713502
PAX8    ?   ?   ? 
GUCA1A  ?   ?   ?

我想要打印多少个“?”由NF决定(在这种情况下为3,但可能多达100)。非常感激任何的帮助! 感谢

3 个答案:

答案 0 :(得分:4)

如果您想假设文件中的最大字段数出现在第1行,请执行以下操作:

$ awk -v OFS="\t" 'NR==1 {cols=NF} {$1=$1; for (i=NF+1; i <= cols; i++) $i = "?"} 1' file
DDR1    8.55578403700418    8.65526857898327    8.71701700266541
MIR4640 8.55578403700418    8.65526857898327    8.71701700266541
RFC2    5.47524925570941    5.88644077981836    5.77277342309348
HSPA6   4.12035662689116    4.01089068869244    3.82366440713502
PAX8    ?   ?   ?
GUCA1A  ?   ?   ?

奇怪的$1=$1位强制awk使用每个行的新OFS重写$ 0,即使for循环没有添加新字段。

如果第1行不一定出现最大字段数,则可以处理该文件两次:一次找到最大数量;一次添加字段占位符:

awk -v OFS="\t" '
    NR == 1 {cols = NF}
    NR == FNR {if (NF>cols) cols=NF; next} 
    {$1=$1; for (i=NF+1; i <= cols; i++) $i = "?"} 
    1
' file file

答案 1 :(得分:0)

<强>输入

DDR1 8.55578403700418 8.65526857898327 8.71701700266541
MIR4640 8.55578403700418 8.65526857898327 8.71701700266541
RFC2  5.47524925570941 5.88644077981836 5.77277342309348
HSPA6 4.12035662689116 4.01089068869244 3.82366440713502
PAX8
GUCA1A

AWK脚本

awk '{
       if($0!=$1){
         printf "%s\n",$0
        }
        else{
        printf "%s\t?\t?\t?\t\n",$1
        }
     }' yourfilename > temp && mv temp yourfilename

<强>输出

DDR1 8.55578403700418 8.65526857898327 8.71701700266541 
MIR4640 8.55578403700418 8.65526857898327 8.71701700266541 
RFC2  5.47524925570941 5.88644077981836 5.77277342309348
HSPA6 4.12035662689116 4.01089068869244 3.82366440713502
PAX8    ?   ?   ?   
GUCA1A  ?   ?   ?

以上

的GNU-Sed一个班轮
sed -i 's/^\([[:alnum:]]*\)$/\1\t?\t?\t?/' yourfilename

答案 2 :(得分:0)

这是我的看法:

<强> script.awk

NR==1 { for(i=2;i<=NF;i++) tmp=tmp "\t?" }
{ if (NF==1) print $1, tmp
  else print }

像这样使用它:awk -f script.awk yourfile

  • 第一行根据第1行中的fieldcount确定仅具有名称的行中输出的模板。
  • 第二个操作会打印行或名称以及模板