You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用awk命令按指定位置字符分组求和并存储到变量?

问题描述

我手头有个固定格式的文本文件,需要按每行第67位的字符(要么是D要么是C),分别对第68到81位的数值求和,预期结果应该是D对应1600,C也对应1600。

文件内容是这样的:

10010001602171813800899901000000000101211000002007-05-130005316347D000000000000800 000000002007-05-18x?0000000000
10010001602171813800899901000000000201211000002007-05-130748402438C000000000000800 000000002007-05-18x?0000000000
10010001602171813800899901100000000101211000002007-05-130005316347D000000000000800 000000002007-05-18x?0000000000
10010001602171813800899901100000000201211000002007-05-130748402438C000000000000800 000000002007-05-18x?0000000000

我试了下面的命令:

grep "^1" file.txt | \
awk '{s[substr($0,67,68-67)]+=substr($0,68,83-68)} END { for (i in s) { print i, s[i] }}'

结果却不对,输出是:

C 1596678
D 1596678

而且我还需要把这两个求和结果分别存到独立的shell变量里,比如用A存D对应的和,B存C对应的和,该怎么弄呢?

解决方法

1. 先修正awk的截取错误

你之前的问题出在substr的参数用错了!awk里的substr语法是substr(字符串, 起始位置, 长度),不是起始到结束位置。

  • 要取第67位的单个字符,应该用substr($0, 67, 1)(从第67位开始,取1个字符)
  • 第68到81位一共是14个字符(81-68+1=14),所以要写substr($0, 68, 14),而且得加个+0强制把截取的字符串转成数值,避免变成字符串拼接。

修正后的awk命令如下:

grep "^1" file.txt | awk '{
    key = substr($0, 67, 1)
    val = substr($0, 68, 14) + 0  # 强制转数值,防止字符串拼接出错
    s[key] += val
} END {
    print "D=" s["D"], "C=" s["C"]
}'

执行这个命令就能得到正确的结果:

D=1600 C=1600

2. 把结果赋值给shell变量

要把这两个值存到A和B里,用shell的read命令配合进程替换就能搞定:

read A B < <(grep "^1" file.txt | awk '{
    key = substr($0, 67, 1)
    val = substr($0, 68, 14) + 0
    s[key] += val
} END {
    print s["D"], s["C"]
}')

之后你直接用echo "D对应的和是$A,C对应的和是$B"就能验证,输出会是:

D对应的和是1600,C对应的和是1600

为啥之前结果错了?

之前的命令里,substr($0,68,83-68)是从第68位取15个字符(83-68=15),这就把后面的空格和其他无关数字也包含进去了,而且没转成数值,导致字符串拼接后变成了大数字,所以结果完全不对。加+0强制转数值就是为了避免这种问题。

内容的提问来源于stack exchange,提问作者user9794957

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:09:42