000Bxxxxx111118064085vxas - header
10000000001000000000053009-000000000053009-
10000000005000000000000000+000000000000000+
10000000030000000004025404-000000004025404-
10000000039000000000004930-000000000004930-
10000000088000005417665901-000005417665901-
90000060883328364801913 - trailer
在上面的文件中我们有标题和预告片,以1开头的记录是详细记录 在详细记录中,想要使用awk / sed命令对从28位到44位开始的值进行求和,包括符号
答案 0 :(得分:1)
使用awk
我们可以使用substr
来解决这个问题:
<强>
substr(s, m[, n ])
强> 返回n
的{{1}}字符子字符串,其位置从s
开始,编号为1.如果省略m
,或n
指定更多字符串中剩余的字符,子字符串的长度应受字符串n
的长度限制。
这允许我们取代表数字的字符串。在这里,我假设数字前后的符号是相同的,因此是数字的符号:
s
由于$ echo "10000000001000000000053009-000000000053009-" \
| awk '{print length($0); print substr($0,27,43-27)}'
43
-000000000053009
隐式将字符串转换为数字,如果对它们进行数值运算,我们可以编写以下awk
- 代码来实现所请求:
awk
或者在一行中:
$ awk '/header|trailer/{next}
{s+=substr($0,27,43-27)}
END{print s}' file.dat
-5421749244
以上示例仅适用于OP提供的示例文件。但是,如果您的文件包含多个$ awk '/header|trailer/{next}{s+=substr($0,27,43-27)} END{print s}' file.dat
-5421749244
和header
的块,并且您只想使用这些块中的文本(排除块之外的所有内容),那么您应该稍微处理一下:
trailer
我们在此处执行以下操作:
$ awk '/header/{s=0;c=1;next}
/trailer/{S+=s;c=0;next}
c{s+=substr($0,27,43-27)}
END{print S}' file.dat
的行,请将块总和header
重置为s
并设置ZERO
,表示我们将下一行考虑在内c=1
的行,请将块总和trailer
添加到总和s
,并设置S
表示忽略这些行。c=0
计算块总和c/=0
s
,打印总金额END
答案 1 :(得分:1)
这是sed,在bc的帮助下做算术:
sed -rn '
/header|trailer/! {
s/[[:digit:]]*[+-]([[:digit:]]+)([+-])$/\2\1/
H
}
$ {
x
s/\n//gp
}
' file | bc
我假设+/-
符号跟随数字。