使用awk BEGIN创建循环

时间:2018-11-14 23:56:19

标签: arrays loops awk

我正在尝试将awk BEGIN代码变成一个循环。原始代码用于基于“批处理”(Batch)列的值编辑数据并输出文件。

这是原始代码(效果很好):

awk '
BEGIN{
  FS=OFS=","
}
FNR==1{
  for(i=1;i<=NF;i++){
    if($i=="YBr"){
       field=i
    }
    if($i=="NationalCowID"){
       value=i
    }
  }
}
$field==1{
  for(i=value+1;i<=NF;i++){
       $i="*"
  }
}
1
' obvs.csv > obvs1.csv

上面的代码采用如下所示的文件obvs.csv:

NationalCowID,TestDate,Batch,LN,DIM,YBr,year,CH4,PLS,qtl
206004574,20141208,6,2,92,1,2014,424.4410055,NA,1
206004573,20141209,6,2,93,2,2014,436.4504712,NA,4
206004575,20141207,6,2,91,1,2014,380.94688,NA,6
206004576,20141208,6,2,92,2,2014,424.4410055,NA,7
206004579,20141209,6,2,93,2,2014,436.4504712,NA,8
206004571,20141207,6,2,91,1,2014,380.94688,NA,9

并编辑数据,使其看起来像这样(obvs1.csv):

NationalCowID,TestDate,Batch,LN,DIM,YBr,year,CH4,PLS,qtl
206004574,*,*,*,*,*,*,*,*,*,1
206004573,20141209,6,2,93,2,2014,436.4504712,NA,4   
206004575,*,*,*,*,*,*,*,*,*,6
206004576,20141208,6,2,92,2,2014,424.4410055,NA,7
206004579,20141209,6,2,93,2,2014,436.4504712,NA,8
206004571,*,*,*,*,*,*,*,*,*,9

我想将此代码转换为循环,以便创建一个新文件,并开始将编辑应用于“ Batch”列(1-6)的每个值。我已经阅读了一些示例和命令说明,但我不完全了解代码各部分的功能。 例如,与已经编码的$ i相比,我如何编码$ j? 这是我尝试创建的循环:

for j in {1..6}
do
awk '
BEGIN{
  FS=OFS=","
}
FNR==$j{
  for(i=1;i<=NF;i++){
    if($i=="Batch"){
       field=i
    }
    if($i=="NationalCowID"){
       value=i
    }
  }
}
$field==1{
  for(i=value+1;i<=NF;i++){
       $i="*"
  }
}
$j
' obvs.csv > obvs$j.csv
done

最后,我希望有6个文件,如下所示:

obvs1.csv -> only lines with batch = 1 are edited
obvs2.csv -> only lines with batch = 2 are edited
obvs3.csv-> only lines with batch = 3 are edited
obvs4.csv-> only lines with batch = 4 are edited
obvs5.csv-> only lines with batch = 5 are edited
obvs6.csv-> only lines with batch = 6 are edited

因此,文件名与“批处理”相对应,该“批处理”用作指示要编辑哪一行的指示器。也就是说,对于obvs2.csv,对于数据行(批处理等于2),除了第一个和最后一个列之外的所有列都将被编辑为*。 到目前为止,我最终得到了6个正确命名的文件,但是文件中的编辑不正确。 任何方向/代码解释都将不胜感激!

2 个答案:

答案 0 :(得分:1)

请您尝试一次。

import numpy as np

def shuffle(data,data_size):
    for step in range(int(1*data_size)):
        selected = int(np.random.uniform(0,data_size))
        target = int(np.random.uniform(0,data_size))   

        print(data)
        if selected!=target:

            data[[selected, target]] = data[[target, selected]]      

            print(selected," and ",target, " are changed")
    return data

data = [[[1,2,3,4],[1,2,3,5],[1,2,3,6]],
        [[2,2,3,4],[2,2,3,5],[2,2,3,6]],
        [[3,2,3,4],[3,2,3,5],[3,2,3,6]] ]

data = np.array(data)
data = shuffle(data,3)

上面的代码将创建2个名为awk ' BEGIN{ FS=OFS="," } FNR==1{ head=$0 next } { count[$6] a[++val]=$0 } END{ for(i in count){ for(j=1;j<=val;j++){ num=split(a[j],array,",") if(!header["output_file"i]++){ print (head) > "output_file"i } if(array[6]==i){ for(k=2;k<=(num-1);k++){ value=value?value OFS "*":"*" } } if(value){ print (array[1],value,array[num]) > "output_file"i } else {print (a[j]) > "output_file"i} value="" } } }' Input_file output_file1的输出文件,您也可以根据需要更改输出文件名。

输出文件的值如下。

output_file2

很快就会添加解释。

编辑: 。现在在代码上方也添加了说明。

cat output_file1
NationalCowID,TestDate,Batch,LN,DIM,YBr,year,CH4,PLS,qtl
206004574,*,*,*,*,*,*,*,*,1
206004573,20141209,6,2,93,2,2014,436.4504712,NA,4
206004575,*,*,*,*,*,*,*,*,6
206004576,20141208,6,2,92,2,2014,424.4410055,NA,7
206004579,20141209,6,2,93,2,2014,436.4504712,NA,8
206004571,*,*,*,*,*,*,*,*,9

cat output_file2
NationalCowID,TestDate,Batch,LN,DIM,YBr,year,CH4,PLS,qtl
206004574,20141208,6,2,92,1,2014,424.4410055,NA,1
206004573,*,*,*,*,*,*,*,*,4
206004575,20141207,6,2,91,1,2014,380.94688,NA,6
206004576,*,*,*,*,*,*,*,*,7
206004579,*,*,*,*,*,*,*,*,8
206004571,20141207,6,2,91,1,2014,380.94688,NA,9

答案 1 :(得分:0)

问题在于您正在混合bash变量和awk变量。因此,建议重复。您提供的awk代码也无法执行您提到的替换。

这是原始代码的外观:

BEGIN{FS=OFS=","}
(FNR==1) { 
   for (i=1;i<=NF;++i) {
      if ($i == "YBr") bfield=i;
      else if ($i == "NationalCowID") cfield=i
   }
}
($bfield == 1) { for(i=cfield+1;i<NF;++i) $i="*" }
1

您现在可以调整以包含$bfield应该具有的值:

awk -v bvalue="$j" '
   BEGIN{FS=OFS=","}
   (FNR==1) { 
      for (i=1;i<=NF;++i) {
         if ($i == "Batch") bfield=i;
         else if ($i == "NationalCowID") cfield=i
      }
   }
   ($bfield == bvalue) { for(i=cfield+1;i<NF;++i) $i="*" }
   1
' file.csv