bash - сумма чисел в переменной

Поскольку никто еще не упомянул об этом (в ответе )еще:

Убедитесь, что у вас есть разрешение на чтение исходного (входного )файла (с ).

  • После подключения к серверу с помощью sshпопробуйте прочитать файлы с помощью
    • catи/или
    • grepи/или
    • wcи или
    • любая программа, которая вам нравится (которая читает файл (s))
  • Попробуйте scp -r user@server:/opt/drop/PATH /tmpилиscp -r user@server:/opt/drop/PATH.
3
04.10.2019, 18:16
7 ответов

Использовать расширение параметра.

#!/bin/bash
VAR=" 2 1  34 3    2 "

shopt -s extglob                # Enable the `+(...)` construct.
expression=${VAR#+(\ )}         # Remove leading spaces.
expression=${expression%+(\ )}  # Remove trailing spaces.
bc <<< ${expression//+(\ )/+}   # Replace strings of spaces by pluses.
4
27.01.2020, 21:07

Несколько приемов Perl:

$ perl -lane '$t+=$_ for @F; print $t' <<<"$var"
42

Или

$ perl -pe 's/(\d)\s+(?=\d)/$1+/g' <<<"$var" | bc
42

Или

$ perl -lane 'print eval join "+", @F' <<<"$var"
42

Или GNU sedи coreutils:

$ tr -s ' ' '+' <<<$var | sed 's/^+//; s/+$//' | bc
42
4
27.01.2020, 21:07

Если вы знаете длину переменной, вы можете использовать awk следующим образом:

echo $VAR | awk '{print $1 + $2 + $3 + $4 + $5}'

Выход:

42

Надеюсь, это поможет.

1
27.01.2020, 21:07

Аналогично решению массива Криса:

$ var=" 2 1  34 3    2 "
$ var=$(echo $var); echo "$((${var// /+}))"
42

Обрежьте и сожмите все символы пробела, затем замените все символы пробела на +и оцените.

4
27.01.2020, 21:07

Пока составляющие числа являются целыми числами, это тоже должно работать (это связано с declareили typesetпринятием арифметического выражения для инициализации целочисленной переменной)

VAR=" 2 1  34 3    2 "
read -r VAR <<<$VAR #shed leading and trailing spaces, compact internal spaces
VAR=${VAR// /+}   #replace spaces with plusses
declare -i var=$VAR     #typeset var to an integer
echo $var
42
0
27.01.2020, 21:07

В исходной строке есть повторяющиеся пробелы и начальные/конечные пробелы.

Наивное преобразование пробелов в +не удастся:

$ value='      2 1  34 3    2    '
$ echo "${value// /+}"
++++++2+1++34+3++++2++++

Чтобы свернуть все повторяющиеся пробелы и удалить начальный/конечный пробел, вам просто нужно echo (или printf )для переменной без кавычек (, предполагая, что IFS используется по умолчанию):

value=$(echo $value)
echo "${value// /+}"
2+1+34+3+2

И это может быть скормлено до н.э.:

$ echo "${value// /+}" | bc
42

Все в одну строку, если хотите:

value=$(echo $value); echo "${value// /+}" | bc

Или, даже используя sedв качестве фильтра (без дополнительной переменной,но медленнее):

echo $value | sed 's/ /+/g' | bc

При предыдущей попытке сделать это с <<<возникла проблема:

$ ~/bin/b44sh -c 'value="      2 1  34 3    2    ";sed "s/ /+/g" <<<$value'
++++++2+1++34+3++++2++++

На bash начиная с версии 4.4. В предыдущих версиях это работало так:

~/bin/b43sh -c 'value="      2 1  34 3    2    ";sed "s/ /+/g" <<<$value'
2+1+34+3+2

Для любой версии bash (и sed )мы можем сделать (довольно надежную версию, но с вызовом внешней утилиты-sed):

sed "s/ \+/+/g" <<<"0 $value 0"     | tee /dev/tty     | bc
0+2+1+34+3+2+0
42

Чистое решение оболочки (требует bash,ksh или zsh для замены ${//}часть )может быть:

value=$(echo $value); bc <<<"${value// /+}

И более надежная(защита ваших предположений™ )и портативная версия:

  • Избегайте влияния изменений IFS на текущую оболочку. Используйте вложенную оболочку (…).
  • убедитесь, что IFS разбивает значения на пробелы (IFS=" ")
  • убедитесь, что даже если строка не заключена в кавычки, она не будет расширяться *et all (установить -f ).
  • убедитесь, что детали соединены с+(IFS=+ ).

( IFS=" "; set -f; set -- $value; IFS=+; echo "$*" | bc; )

Версия функции
1 -, если ваша оболочка не поддерживает local, используйте более медленную форму оболочки sub -
2 -Некоторые (правильно в POSIX )могут жаловаться на использование $*без кавычек.

sum(){ local IFS=" "; set -f; set -- $*; IFS=+; echo "$*" | bc; }

Что во многом добавляет аргументов

$ value="      2 1  34 3    2    "
$ sum "$value"
42
$ sum $value    # beware of glob chars *, ? and [  and of odd IFS=123 settings
42
$ sum "      2 1  34 3    2    "
42
$ sum "      2"    "1  "    "34 3"    "    2    "
42
$ var=23
$ sum "      2"    "1  "    "34 3"    "    2    "   "$var"
65
4
27.01.2020, 21:07

bash-скрипты:

$ v="2 4 7 10 3"
$ s=0
$ for i in $v
> do
> s=$((s+i))
> done
$ echo $s
26
2
27.01.2020, 21:07

Теги

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