【问题标题】:awk slab calculation based on range基于范围的awk平板计算
【发布时间】:2014-06-13 22:40:24
【问题描述】:

想根据 StartRange、EndRange、Category 和 Flag_value 信息计算平板计算。

SampleInput.txt

Field1,Field2,Field3,Field4,Field5,Field6
Desc,Name,Category,Desc2,Flag_Value,Slab_Count
ZZZ,ABC,A,xyz,2,140
ZZZ,CDE,A,xyz,-5,140
ZZZ,FGH,B,xyz,10,48
ZZZ,IJK,B,xyz,-10,48
ZZZ,LMN,C,xyz,115,248
ZZZ,OPQ,A,ijk,-62,250
ZZZ,RST,D,ijk,67,350
ZZZ,UVW,A,ijk,-80,5
ZZZ,XYZ,A,ijk,48,6

平板.txt

StartRange,EndRange,Category-A,Category-B,Category-C,Category-D,Flag_Value
1,50,350,350,500,500,-125
51,100,450,500,550,600,-150
101,150,600,600,600,650,-150
151,200,700,650,650,650,-200
201,250,800,750,700,700,-250
251,1000,900,850,800,800,-300

SampleInput.txt第一行的计算方法,需要从SampleInput.txt Field3(即A),Field5>0(即2)和Field6(即140)中取输入 然后从 Slab.txt 中查找数据以找到位于范围(即 101,150,600,600,600,650,-150),类别(即类别 A)并打印相应的值,即 600

SampleInput.txt 的第二行,需要从 SampleInput.txt Field3 (i.e A) , Field5

预期输出.txt

Desc,Name,Category,Desc2,Flag_Value,Slab_Count,Slab_Amt
ZZZ,ABC,A,xyz,2,140,600
ZZZ,CDE,A,xyz,-5,140,450
ZZZ,FGH,B,xyz,10,48,350
ZZZ,IJK,B,xyz,-10,48,225
ZZZ,LMN,C,xyz,115,248,700
ZZZ,OPQ,A,ijk,-62,250,550
ZZZ,RST,D,ijk,67,350,800
ZZZ,UVW,A,ijk,-80,5,225
ZZZ,XYZ,A,ijk,48,6,350

在谷歌中搜索了很多相关尝试,但没有找到相同的,卡在复杂的级别上寻找,寻找您的建议。

【问题讨论】:

    标签: awk


    【解决方案1】:

    这是另一种可能性:

    awk '
    BEGIN { FS = OFS = "," } 
    NR == 1 { next } 
    FNR == 1 { print $0, "Slab_Amt" }
    NR == FNR { 
        range[$1,$2,"A"] = $3
        range[$1,$2,"B"] = $4
        range[$1,$2,"C"] = $5
        range[$1,$2,"D"] = $6
        flag[$1,$2] = $NF
        next
    }   
    {
        for (key in range) {
            split (key, tmp, SUBSEP);
            if (tmp[3] == $3 && tmp[1] <= $NF && $NF <= tmp[2]) {
                value = ( $5 > 0 ? range[key] : range[key] + flag[tmp[1],tmp[2]] )
                print $0, value
                next
            }
        }
    }' Slab.txt SampleInput.txt
    

    输出:

    Desc,Name,Category,Desc2,Flag_Value,Slab_Count,Slab_Amt
    ZZZ,ABC,A,xyz,2,140,600
    ZZZ,CDE,A,xyz,-5,140,450
    ZZZ,FGH,B,xyz,10,48,350
    ZZZ,IJK,B,xyz,-10,48,225
    ZZZ,LMN,C,xyz,115,248,700
    ZZZ,OPQ,A,ijk,-62,250,550
    ZZZ,RST,D,ijk,67,350,800
    ZZZ,UVW,A,ijk,-80,5,225
    ZZZ,XYZ,A,ijk,48,6,350
    

    说明:

    • 我们使用BEGIN { FS = OFS = "," } 将输入和输出字段分隔符设置为,
    • 如果它是第一个文件的第一行,我们使用NR == 1 { next } 跳过它
    • 对于第二个文件的第一行,我们使用FNR == 1 { print $0, "Slab_Amt" } 打印添加Slab_Amt 作为标题
    • 我们遍历Slab.txt 文件,将每个类别的值存储在我们的多维数组中,将开始范围、结束范围和类别作为range 数组中的键。
    • 我们将标志值存储在flag 数组中,该数组在开始和结束范围内键入。
    • 当我们开始处理 SampleInput.txt 文件时,我们会迭代我们的范围数组并拆分键。
    • 我们检查我们的键的第三部分是否等于样本输入的第三列,并且最后一列是否在我们的范围之间。如果是,我们通过检查第 5 列是否大于 0 来计算值。如果是,我们只需分配范围的值,否则,我们将范围值添加到标志值并与我们的值一起打印该行。李>
    • 使用next,我们跳过进一步检查并移至下一行样本输入。

    【讨论】:

    • 非常感谢 Jaypal,它工作正常,请您提供一些解释以理解代码
    • @AVN 已添加说明。希望对您有所帮助。
    • @AVN 除了 jaypal 的解释,你还需要阅读gnu awk manual(或其他一些手册/书籍)来学习语言。
    【解决方案2】:

    这是一种可能性。

    awk -F, '
    BEGIN {
      getline <"Slab.txt"  # skip header
      while ((getline <"Slab.txt") > 0)
        slabs[int($2)] = $0
      # Last index must be greater than top of range
      slabs[999999] = "endmarker"
    }
    NR == 2 { print $0",Slab_Amt" }
    NR > 2 {
      n = int($6)
      for (rangetop in slabs)
        if (n <= int(rangetop))
          break
      if (rangetop == 999999) {
        print "n out of range:",n >"/dev/stderr"
        exit(1)
      }
      split(slabs[rangetop], fields, ",")
      switch ($3) {
      case "A":  val = fields[3]; break
      case "B":  val = fields[4]; break
      case "C":  val = fields[5]; break
      case "D":  val = fields[6]; break
      default:
        print "unknown category:",$3 >"/dev/stderr"
        exit(1)
      }
      if ($5 < 0)
         val += fields[7]
      print $0","val
    }
    ' SampleInput.txt
    

    【讨论】:

    • 非常感谢 @ooga 的输入,但输出似乎不正确 ,Desc,Name,Category,Desc2,Flag_Value,Slab_Count, ZZZ,ABC,A,xyz,2,140,​​800 ZZZ,CDE,A,xyz ,-5,140,​​550
    • 预期输出 Desc,Name,Category,Desc2,Flag_Value,Slab_Count,Slab_Amt ZZZ,ABC,A,xyz,2,140,​​600 ZZZ,CDE,A,xyz,-5,140,​​450
    • 这可能是因为我假设标题实际上不在数据文件中。我会编辑它,但无论如何我更喜欢 jaypal 的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多