команда awk или команда sed - PullRequest
0 голосов
/ 15 мая 2018
000Bxxxxx111118064085vxas - header 
10000000001000000000053009-000000000053009-
10000000005000000000000000+000000000000000+
10000000030000000004025404-000000004025404-
10000000039000000000004930-000000000004930-
10000000088000005417665901-000005417665901-
90000060883328364801913 - trailer 

В приведенном выше файле у нас есть заголовок и трейлер, а записи, которые начинаются с 1, являются подробными записями в подробных записях, мы хотим суммировать значения, начиная с позиции 28 до 44, включая знак, используя команду awk / sed

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Вот sed, с помощью bc, чтобы выполнить арифметику:

sed -rn '
    /header|trailer/! {
        s/[[:digit:]]*[+-]([[:digit:]]+)([+-])$/\2\1/
        H
    }
    $ {
        x
        s/\n//gp
    }
' file | bc

Я предполагаю, что знак +/- следует за числом.

0 голосов
/ 15 мая 2018

Используя awk, мы можем решить эту проблему, используя substr:

substr(s, m[, n ]): Возврат не более n -строка подстрока s, которая начинается в позиции m, нумерация от 1. Если 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

или в одну строку:

$ awk '/header|trailer/{next}{s+=substr($0,27,43-27)} END{print s}' file.dat
-5421749244

Приведенные выше примеры работают только с файлом примера, заданным OP.Однако, если у вас есть файл, содержащий несколько блоков с 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 выведите общую сумму S
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...