Сообщение «Ошибка сегментации (дамп ядра)» выдается bash, а не программой, в которой произошел сбой (когда сообщение отправлено, программа уже мертва!). Перенаправление относится только к самой программе.
Чтобы перенаправить сообщения о программе из самой оболочки, запустите программу внутри группирующей конструкции оболочки и перенаправьте вывод всей группы. Самая основная конструкция группировки оболочки, которая ничего не делает, кроме группы, - это фигурные скобки.
ret=`{ ./segfault; } 2>&1`
Форма ret = `eval ./segfault 2> & 1`
применяет перенаправление ко всей оценке команды eval
, так что в принципе она должна работать, и это действительно так. фактически работаю на моей машине с bash 4.3.30 и более ранними версиями. Что может происходить (и я могу воспроизвести это с помощью ksh), так это то, что ваша версия bash делает некоторые оптимизации, чтобы избежать разветвления подпрограмм, когда они являются последней командой в подоболочке. Номинальный способ выполнить команду ret = `eval ./segfault`
:
eval
. ./ segfault
, т.е. заменить программу оболочки, которая в данный момент выполняется в этом процессе, на Программа segfault
. ret
. Как видите, процесс 1 создает другой процесс, затем ожидает его завершения и немедленно завершает работу. Было бы более эффективно, если бы процесс 1 перерабатывал сам себя. Некоторые оболочки (и версии оболочки) лучше других распознают такие ситуации и выполняют оптимизацию хвостовых вызовов . Однако в случае ret = `{./segfault; } 2> & 1`
, процесс 2 имеет стандартную ошибку, перенаправленную на файловый дескриптор 1, а процесс 1 - нет. В версии оболочки, которую вы пробовали, оптимизатор не распознал эту ситуацию (он мог выполнить хвостовой вызов, но он должен был настроить перенаправление по-другому).
Вот 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]}}
-просто напечатайте содержимое массива Steeldriver немного опередил меня, но я придумал
perl -F'[=,]' -lane '
%row = @F;
$sum{$row{55}} += $row{38};
}{
print "$_ = $sum{$_}" for keys %sum
' file.csv
XYZ = 1000
ZYX = 400
с использованием Миллера 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