使用两个值计算通过管道传输到 awk 的小数输入,这两个值都出现在不同的行上并每第 n 行重复一次?

使用两个值计算通过管道传输到 awk 的小数输入,这两个值都出现在不同的行上并每第 n 行重复一次?

我已将输入通过管道传输到 macOS 系统上的 awk。我想要两个小数值的总和。一个每隔两行出现一次,另一个每隔四行出现一次。我想要每第五行的总和结果。这些值之前由冒号+空格分隔,之后由逗号分隔。每第六行都是空的。此模式会重复,直到输入结束。

BB: 728345643856359022, 
SH: 3560836, 
RJ: 1500369, 
DD: 1403849, 
Total:,

BB: 729586953244932948, 
SH: 8560836, 
RJ: 4700360, 
DD: 3403021, 
Total:,

BB: 821334125345384020, 
SH: 5293431, 
RJ: 2642499, 
DD: 2433292, 
Total:,

如果相关,which awk输出/usr/bin/awkbrew list --version输出gawk 5.2.1_1。这在 g/awk 中可能吗?任何建议表示赞赏!

要格式化我正在使用的输入:

getlist | awk '{print $1 $2}' \
| grep 'BB\|SH\|RJ\|DD' \
| sed 's/"//g' \
| awk '{print;} NR % 4 == 0 { print "Total:,";}' \
| awk '{print;} NR % 5 == 0 { print "";}' \
| awk '{print $1 $2}'

预期产出

BB: 728345643856359022, 
SH: 3560836, 
RJ: 1500369, 
DD: 1403849, 
Total: 4964685,

BB: 729586953244932948, 
SH: 8560836, 
RJ: 4700360, 
DD: 3403021, 
Total: 11963857,

BB: 821334125345384020, 
SH: 5293431, 
RJ: 2642499, 
DD: 2433292, 
Total: 7726723,

答案1

首先,让我们稍微简化一下您的管道。我不知道getlist会产生什么输出,但根据您所显示的内容,这相当于不添加该Total行的微小更改,因为这只会使解析变得更加困难,我们稍后将添加它:

getlist | 
 tr -d '"' |
 awk '/BB|SH|RJ|DD/{print $1 $2}; NR % 5 == 0 { print ""}' 

您可以在 处换行|,无需\。您可以将所有步骤合并为一个awk,并使用tr代替sed来简化(并且可能提高速度,尽管这里的差异很小)。

考虑到这一点,我们可以awk稍微扩展一下以获得剩余的部分:

getlist | 
 tr -d '",' |
 awk '/BB|SH|RJ|DD/{
        print $1 $2","; 
        if(/SH/){ sh = $2 } 
        if(/DD/){ printf "Total: %d,\n", sh + $2 }
      }
      NR % 5 == 0 { print ""}' 

请注意,我添加了要删除,的字符tr以方便数字运算(,不是数字),因此我还将其添加回printawk 中的各种调用中。


如果我误解了,这里有一种方法可以使用原始管道中已有的输出来执行相同的操作(我将示例另存为file):

$ awk '{ 
         if(!/Total/){print; 
           if(/SH/){ sh = $2 } 
           if(/DD/){ val = sh + $2 }
         }
         else{
            print "Total:",val","
         }
        }' file
BB: 728345643856359022, 
SH: 3560836, 
RJ: 1500369, 
DD: 1403849, 
Total: 4964685,

BB: 729586953244932948, 
SH: 8560836, 
RJ: 4700360, 
DD: 3403021, 
Total: 11963857,

BB: 821334125345384020, 
SH: 5293431, 
RJ: 2642499, 
DD: 2433292, 
Total: 7726723,

答案2

每当您的数据中有标记值对时,我发现最好首先创建这些映射的数组(m[]如下),然后您只需通过使用关联名称索引该数组即可获取任何值。使用任何 awk:

$ awk -F': *' -v OFS=': ' '{m[$1]=$2} $1=="Total"{$2=(m["SH"] + m["DD"])","} 1' file
BB: 728345643856359022,
SH: 3560836,
RJ: 1500369,
DD: 1403849,
Total: 4964685,

BB: 729586953244932948,
SH: 8560836,
RJ: 4700360,
DD: 3403021,
Total: 11963857,

BB: 821334125345384020,
SH: 5293431,
RJ: 2642499,
DD: 2433292,
Total: 7726723,

答案3

这是一种方法,它可以利用现有的输出并实现新的所需输出。与 gawk 5.1.0 一起工作正常。

$ awk '/^SH/{a=$2}/^DD/{b=$2}/^Total/{$0="Total: "a+b","}1' input.txt
BB: 728345643856359022,
SH: 3560836,
RJ: 1500369,
DD: 1403849,
Total: 4964685,

BB: 729586953244932948,
SH: 8560836,
RJ: 4700360,
DD: 3403021,
Total: 11963857,

BB: 821334125345384020,
SH: 5293431,
RJ: 2642499,
DD: 2433292,
Total: 7726723,
$

相关内容