awk命令或sed命令

时间:2018-05-15 14:59:43

标签: awk sed

000Bxxxxx111118064085vxas - header 
10000000001000000000053009-000000000053009-
10000000005000000000000000+000000000000000+
10000000030000000004025404-000000004025404-
10000000039000000000004930-000000000004930-
10000000088000005417665901-000005417665901-
90000060883328364801913 - trailer 

在上面的文件中我们有标题和预告片,以1开头的记录是详细记录 在详细记录中,想要使用awk / sed命令对从28位到44位开始的值进行求和,包括符号

2 个答案:

答案 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

我假设+/-符号跟随数字。