Поскольку вы используете v11.3, вы также можете переключиться с использования SunSSH на OpenSSH, если хотите.
Вот процесс, взятый из шпаргалки по Solaris 11, составленной Йоргом:
Начиная с Solaris 11.3 можно использовать OpenSSH вместо SunSSH.
pkg install openssh
pkg mediator -a ssh
pkg set-mediator -I openssh ssh
cat numbers.txt | awk '{sum += $1; if (NR % 5 == 0) {print sum; sum=0}} END {if (NR % 5 != 0) print sum}'
sum
начинается как 0 в awk. Каждая пятая строка выводит текущую сумму чисел, затем сбрасывает сумму до нуля и переходит на следующие пять строк. END
в конце обрабатывает крайний регистр числа строк в файле, не кратного пяти, например, если в файле 18 строк, он напечатает сумму последних 3 строк. Он также обрабатывает крайний случай непечатания нежелательного нуля, когда число строк кратно пяти.
sed '$!N;$!N;$!N;$!N;s/\n/+/g' list.txt | bc
Демонстрация:
$ seq 33 | sed '$!N;$!N;$!N;$!N;s/\n/+/g'
1+2+3+4+5
6+7+8+9+10
11+12+13+14+15
16+17+18+19+20
21+22+23+24+25
26+27+28+29+30
31+32+33
$ seq 33 | sed '$!N;$!N;$!N;$!N;s/\n/+/g' | bc
15
40
65
90
115
140
96
$
Этот подход имеет несколько преимуществ:
Если вы хотите отбросить лишние (например, отбросить с 31 по 33 в приведенном выше примере), вы можете избавиться от всех $!
условия; это более простая команда, и это была моя первая попытка:
$ seq 33 | sed 'N;N;N;N;s/\n/+/g'
1+2+3+4+5
6+7+8+9+10
11+12+13+14+15
16+17+18+19+20
21+22+23+24+25
26+27+28+29+30
$
во-первых, потому что это просто требует xargs:
<file xargs -rn5 perl -e 'foreach(@ARGV){$a+$_};print $a,"\n"'
но для скорости вы действительно хотите минимизировать количество вызовов интерпретатора, поэтому я будет использовать
perl -e 'while(!eof(ARGV){print <>+<>+<>+<>+<>,"\n"}' file
и цикл оболочки (без проверки ошибок; предполагает четное кратное 5 числам):
while read a; do read b; read c; read d; read e; echo $((a+b+c+d+e)); done < input
Вы можете преобразовать список значений в строки с 5 значениями с помощью столбца .
Предполагая, что вкладки состоят из 8 пробелов (и значения меньше этого):
$ column -c 40 -x infile
1 2 3 4 5
6 7 8 9 10
1 0 2 3 0
0 1 0 0 2
0 3 0 4 0
5 0 2
И переведите каждую вкладку в + для подачи bc:
$ column -c 40 -x infile | tr '\t' '+'
1+2+3+4+5
6+7+8+9+10
1+0+2+3+0
0+1+0+0+2
0+3+0+4+0
5+0+2
$ column -c 40 -x infile | tr '\t' '+' | bc
15
40
6
3
7
7
Возможно, awk будет лучше:
$ column -c 40 -x infile | awk '{print($1+$2+$3+$4+$5)}'
15
40
6
3
7
7
Это только один вызов каждой программы, обе программы запустятся одновременно из-за пайпа и будут работать параллельно.
Время дает мне (при очень медленном процессоре) всего 0,350 секунды для файла из 100 000 строк.
И всего 0,148 секунды, если результат идет в файл (не на экран).
Да, это обрабатывает неполные строки, файлы, которые заканчиваются цифрами 1, 2, 3 или 4. Это будет работать правильно, если числа меньше 1 000 000.
Для больших чисел (до суммы (2^62)-1 9223372036854775807 ~9e18 в 64-битной системе) потребуется что-то вроде:
$ xargs -n 5 -a infile| awk '{print($1+$2+$3+$4+$5)}'
Но это довольно медленнее (38,8 секунды), переключение на чистый awk
$ awk '{s+=$0};NR%5{next};!(NR%5){print(s);s=0}END{if(s){print(s)}}' infile
Или, если вам нужна трубка, используйте:
$ cat infile | awk '{s+=$0};NR%5{next};!(NR%5){print(s);s=0}END{if(s){print(s)}}'
Занимает около 0,150 секунды. Мне кажется, это достаточно быстро.
Если ваши данные имеют точное число, кратное 5 строкам, вы можете изменить head
/ tail
цикл оболочки + paste
Команда для использования только paste
, т.е.
yourcommand | paste -d+ - - - - | bc
Лучшим вариантом может быть использование разбиения на страницы pr
, чтобы упорядочить вывод в 5 столбцов, разделенных +
yourcommand | pr -ats+ -5 | bc
-a
печатать столбцы поперек, а не вниз -t
опускать верхние и нижние колонтитулы страниц -s+
установить разделитель столбцов на +
вместо вкладки по умолчанию В отличие от paste
, pr
работает правильно в случае неполных строк, например использование cat STDOUT
для имитации вывода вашей команды
$ cat STDOUT | pr -ats+ -5
1+0+2+3+0
0+1+0+0+2
0+3+0+4+0
5+0+2
откуда
$ cat STDOUT | pr -ats+ -5 | bc
6
3
7
7
Команда rs
кажется еще одним хорошим кандидатом, однако очевидным кажется rs -C+ 0 5
чтобы добавить конечные разделители.