кумулятивные итоги со смещенным столбцом

кумулятивные итоги со смещенным столбцом

Заранее извиняюсь, так как уверен, что это простая проблема. Тем не менее, вот.

cat blah.txt
aa+2
bb+4
cc+10
dd+31

Я хотел бы обработать blah.txt, чтобы получить следующее:

aa+0
bb+2
cc+6
dd+16

Идея здесь в том, что первый столбец может быть списком песен, а второй — временем их начала.

Моя интуиция подсказывала мне сделать это с помощью awk. Я подумал о двух массивах с числовыми индексами, хранящими $1 и текущую сумму $2. Моя идея состояла в том, чтобы сместить числовой индекс для текущих сумм на 1.

tail -r blah.txt | 
awk -F "+" '{ for(i=0;i<=NR;i++) arr[i+1]+=$2; farr[i]=$1 } END 
{ for(i=NR+1;i>1;i--) {if (i==NR) {print farr[NR] FS 0 } 
else { print farr[i] FS arr[i]}}}'

Это не лаконично, и, что еще хуже, не работает. Я сбит с толку неудачей создания массива, прежде всего.

В любом случае, нуф сказал, может ли какой-нибудь добрый человек избавить меня от моих страданий?

Том

решение1

Ну вот:

$ awk -F+ '{sum+=$2;printf("%s+%d\n",$1,sum-$2);}' blah.txt
aa+0
bb+2
cc+6
dd+16

Edit1: вот немного более простой способ, спасибо Sukminder

$ awk -F+ '{printf("%s+%d\n",$1,sum);sum+=$2}' blah.txt

Редактирование 2: И немного более кратко, спасибо Бернхарду:

$ awk -F+ '{print $1,sum;sum+=$2}' OFS="+" blah.txt

Edit3: но в первом варианте не отображается 0 в первой строке, поэтому вот исправленная и несколько сжатая версия, которая показывает более короткий способ ответить на вопрос Тома (пока какой-нибудь новый комментарий не предложит лучший вариант):

$ awk -F+ '{print$1,s+0;s+=$2}' OFS=+ blah.txt

решение2

Лучший способ сделать это — изучить и использовать регулярные выражения, поскольку в будущем это избавит вас от множества проблем, связанных с выполнением подобных задач.

cat blah.txt | gawk 'match($0, /([^0-9]*)([0-9]+)/, ary) {print ary[1] ary[2]-2}'

Вам придется заменить последние 2 на вашу переменную сдвига. Вы должны обратить внимание на использование gawk. Насколько мне известно, регулярные awkвыражения не могут извлекать группы из регулярных выражений.

Что это делает? Он выполняет сопоставление с $0, помещая результаты в ary, используя регулярное выражение /([^0-9]*)([0-9]+)/, которое сопоставляет: ([^0-9]*)- 0 или более символов, которые не являются числами, и помещает их в первый индекс массива (скобки отвечают за то, что называется группировкой), затем ([0-9]+)сопоставляет число ненулевой длины (и помещает его как второй элемент массива).

Конечно, это можно сделать более детально, добавив проверку ошибок, особые случаи сопоставления и т. д., но я рекомендую вам изучить это (а именно регулярные выражения) самостоятельно.

Связанный контент