
我已将输入通过管道传输到 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/awk
和brew 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
以方便数字运算(,
不是数字),因此我还将其添加回print
awk 中的各种调用中。
如果我误解了,这里有一种方法可以使用原始管道中已有的输出来执行相同的操作(我将示例另存为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,
$