CSV Файл: Группа и сумма Значения на основе первого рисунка каждого значения

Сообщение «Ошибка сегментации (дамп ядра)» выдается bash, а не программой, в которой произошел сбой (когда сообщение отправлено, программа уже мертва!). Перенаправление относится только к самой программе.

Чтобы перенаправить сообщения о программе из самой оболочки, запустите программу внутри группирующей конструкции оболочки и перенаправьте вывод всей группы. Самая основная конструкция группировки оболочки, которая ничего не делает, кроме группы, - это фигурные скобки.

ret=`{ ./segfault; } 2>&1`

Форма ret = `eval ./segfault 2> & 1` применяет перенаправление ко всей оценке команды eval , так что в принципе она должна работать, и это действительно так. фактически работаю на моей машине с bash 4.3.30 и более ранними версиями. Что может происходить (и я могу воспроизвести это с помощью ksh), так это то, что ваша версия bash делает некоторые оптимизации, чтобы избежать разветвления подпрограмм, когда они являются последней командой в подоболочке. Номинальный способ выполнить команду ret = `eval ./segfault`:

  • Создать канал.
  • Форк, т.е. создание подпроцесса оболочки. В подпроцессе (процесс 1):
    • Перенаправить вывод в канал.
    • Выполнить встроенную команду eval eval .
    • Вилка. В подпроцессе (процесс 2):
      • Выполнить файл ./ segfault , т.е. заменить программу оболочки, которая в данный момент выполняется в этом процессе, на Программа segfault .
    • (В процессе 1) Дождитесь завершения процесса 2.
    • Процесс 1 завершается.
  • (В исходном процессе оболочки) Считывание из конвейера и накопление данных в переменной ret .
  • Когда труба закрыта, продолжить выполнение.

Как видите, процесс 1 создает другой процесс, затем ожидает его завершения и немедленно завершает работу. Было бы более эффективно, если бы процесс 1 перерабатывал сам себя. Некоторые оболочки (и версии оболочки) лучше других распознают такие ситуации и выполняют оптимизацию хвостовых вызовов . Однако в случае ret = `{./segfault; } 2> & 1` , процесс 2 имеет стандартную ошибку, перенаправленную на файловый дескриптор 1, а процесс 1 - нет. В версии оболочки, которую вы пробовали, оптимизатор не распознал эту ситуацию (он мог выполнить хвостовой вызов, но он должен был настроить перенаправление по-другому).

2
03.10.2018, 00:35
3 ответа

Вот awkрешение.

awk -F, '{for(a=1;a++<=NF;){
          if($a~/^55=/){l=$a}
          if($a~/^38=/){b[l]+=substr($a,4)}
         }}END{for(x in b){print x,"38="b[x]}}' inp
  • for(a=1;a++<=NF;){-перебор каждой запятой -поле с разделителями
  • if($a~/^55=/){l=$a}-если мы находим поле, начинающееся с 55=, то сохраняем его в переменнойl
  • if($a~/^38=/){b[l]+=substr($a,4)}-если мы находим поле, начинающееся с 38=, берем значение после =и накапливаем его в массиве b, используя переменную lв качестве ключа
  • }}END{for(x in b){print x,"38="b[x]}}-просто напечатайте содержимое массива
1
27.01.2020, 21:58

Steeldriver немного опередил меня, но я придумал

perl -F'[=,]' -lane '
        %row = @F;
        $sum{$row{55}} += $row{38};
    }{ 
        print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400
1
27.01.2020, 21:58

с использованием Миллера http://johnkerl.org/miller/doc, начиная с этогоinput.csv

35=D,11=ABCD1,1=ABC,55=XYZ,38=100,40=P,18=M,54=1,59=0,10=111 35=D,11=ABCD2,1=ABC,55=XYZ,40=P,18=M,38=200,54=1,44=10.00,59=0,10=133 35=D,11=ABCD3,1=ABC,55=XYZ,40=P,18=M B,54=1,38=300,44=10.00,59=0,110=200,10=113 35=D,11=ABCD4,1=ABC,55=XYZ,38=400,40=P,18=M B F,54=1,44=10.00,59=0,110=300,10=144 35=D,11=ABCD5,1=ABC,55=ZYX,38=300,40=2,54=1,44=10.00,59=3,10=132 35=D,11=ABCD6,1=ABC,55=ZYX,38=100,40=1,18=C,54=2,59=3,10=131

и работает

mlr --ofs " " unsparsify then stats1 -a sum -f 38 -g 55 then rename 38_sum,38 input.csv

У вас будет

55=XYZ 38=1000 55=ZYX 38=400

3
27.01.2020, 21:58

Теги

Похожие вопросы