расчет сляба awk на основе диапазона

#awk

#awk

Вопрос:

Хотелось бы рассчитать вычисление сляба на основе информации 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
  

Slab.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 (т.е. A), Field5<0 (т.е. -5) и Field6 (т.е. 140) затем выполняют поиск данных из Slab.txt чтобы найти диапазон лежания (например, 101,150,600,600,600,650, -150), категория (i.Категория e-A) и выведите соответствующее значение дополнительной категории-A Flag_Value, т.е. 450 (600-150)

Ожидаемый Output.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
  

много искал в Google, чтобы найти соответствующие попытки, и не смог найти то же самое, застрял, чтобы найти на сложном уровне, ищу ваши предложения.

Ответ №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 amp;amp; tmp[1] <= $NF amp;amp; $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 }
  • Для первой строки нашего второго файла мы печатаем добавление заголовка Slab_Amt as с помощью FNR == 1 { print $0, "Slab_Amt" }
  • Мы перебираем Slab.txt файл, хранящий значения каждой категории в нашем многомерном массиве, имеющем начальный диапазон, конечный диапазон и категорию в качестве ключей в range массиве.
  • Мы сохраняем значение флага в flag массиве с ключом в начальном и конечном диапазонах.
  • Когда мы начинаем обрабатывать SampleInput.txt файл, мы повторяем наш массив диапазонов и разделяем ключ.
  • Мы проверяем, равна ли третья часть нашего ключа 3-му столбцу выборки входных данных, а последний столбец находится между нашими диапазонами. Если это так, мы вычисляем значение, проверяя, больше ли 5-й столбец 0. Если это так, мы просто присваиваем значение нашего диапазона, если нет, мы добавляем значение диапазона к значению флага и печатаем строку вместе с нашим значением.
  • Используя next , мы пропускаем дальнейшие проверки и переходим к следующей строке ввода образца.

Комментарии:

1. Большое спасибо, Jaypal, все работает нормально, не могли бы вы дать некоторые пояснения, чтобы понять код

2. @AVN добавили объяснение. Надеюсь, это поможет.

3. @AVN В дополнение к объяснению jaypal вам необходимо прочитать руководство gnu awk (или какое-либо другое руководство / книгу), чтобы выучить язык.

Ответ №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
  

Комментарии:

1. Большое спасибо @ ooga за ваши данные, но, похоже, неверный вывод, Desc, Name, Category, Desc2, Flag_Value, Slab_Count, ZZZ, ABC, A, xyz,2,140,800 ZZZ, CDE,A, xyz, -5,140,550

2. ожидаемый результат Desc, Name,Category, Desc2,Flag_Value, Slab_Count,Slab_Amt ZZZ,ABC,A,xyz,2,140,600 ZZZ,CDE,A,xyz,-5,140,450

3. Вероятно, это потому, что я предполагал, что заголовков на самом деле не было в файлах данных. Я отредактирую его, но в любом случае я предпочитаю ответ джейпала.