Сложение целых чисел через каждые 5 строк

Поскольку вы используете v11.3, вы также можете переключиться с использования SunSSH на OpenSSH, если хотите.

Вот процесс, взятый из шпаргалки по Solaris 11, составленной Йоргом:

Начиная с Solaris 11.3 можно использовать OpenSSH вместо SunSSH.

pkg install openssh

pkg mediator -a ssh

pkg set-mediator -I openssh ssh
1
22.06.2017, 04:37
6 ответов
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 строк. Он также обрабатывает крайний случай непечатания нежелательного нуля, когда число строк кратно пяти.

2
27.01.2020, 23:11
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
$ 

Этот подход имеет несколько преимуществ:

  1. Простой
  2. Быстрый
  3. Четкое отделение группировки чисел от математики
  4. Правильно обрабатывает случаи 0 строк, 1 строки, 5n строк и не -multiple-of-5 rows

Если вы хотите отбросить лишние (например, отбросить с 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
$ 
2
27.01.2020, 23:11

во-первых, потому что это просто требует xargs:

<file xargs -rn5 perl -e 'foreach(@ARGV){$a+$_};print $a,"\n"'

но для скорости вы действительно хотите минимизировать количество вызовов интерпретатора, поэтому я будет использовать

perl -e 'while(!eof(ARGV){print <>+<>+<>+<>+<>,"\n"}' file
1
27.01.2020, 23:11

и цикл оболочки (без проверки ошибок; предполагает четное кратное 5 числам):

while read a; do read b; read c; read d; read e; echo $((a+b+c+d+e)); done < input
2
27.01.2020, 23:11

Вы можете преобразовать список значений в строки с 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 секунды. Мне кажется, это достаточно быстро.

1
27.01.2020, 23:11

Если ваши данные имеют точное число, кратное 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 чтобы добавить конечные разделители.

2
27.01.2020, 23:11

Теги

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