Поскольку никто еще не упомянул об этом (в ответе )еще:
Убедитесь, что у вас есть разрешение на чтение исходного (входного )файла (с ).
ssh
попробуйте прочитать файлы с помощью cat
и/или grep
и/или wc
и или scp -r user@server:/opt/drop/PATH /tmp
илиscp -r user@server:/opt/drop/PATH.
Использовать расширение параметра.
#!/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.
Несколько приемов 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
Если вы знаете длину переменной, вы можете использовать awk следующим образом:
echo $VAR | awk '{print $1 + $2 + $3 + $4 + $5}'
Выход:
42
Надеюсь, это поможет.
Аналогично решению массива Криса:
$ var=" 2 1 34 3 2 "
$ var=$(echo $var); echo "$((${var// /+}))"
42
Обрежьте и сожмите все символы пробела, затем замените все символы пробела на +
и оцените.
Пока составляющие числа являются целыми числами, это тоже должно работать (это связано с 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
В исходной строке есть повторяющиеся пробелы и начальные/конечные пробелы.
Наивное преобразование пробелов в +
не удастся:
$ 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// /+}
И более надежная(защита ваших предположений™ )и портативная версия:
(…)
. *
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
bash-скрипты:
$ v="2 4 7 10 3"
$ s=0
$ for i in $v
> do
> s=$((s+i))
> done
$ echo $s
26