Chr*_*ris 4 bash arithmetic bc variable
我有一个变量集,其中的数字用空格分隔,其中第一个数字也可以由空格引导,例如:
VAR=" 2 1 34 3 2 "
Run Code Online (Sandbox Code Playgroud)
我需要将所有这些数字相加。最简单的方法是将数字之间的所有空格替换为+
bc 上的管道
我可以用 for 循环、粘贴和 bc 来完成,但也许有人知道更简单的方法?也许直接在 bash 中VAR
使用 bash 内置字符串替换进行一些计算?
$ for i in $VAR;do echo $i;done|paste -sd+|bc
42
Run Code Online (Sandbox Code Playgroud)
更新:感谢所有建议,我终于找到了带有数组的相当短的方法:
$ VAR=" 2 1 34 3 2 "
$ arr=( $VAR );echo "$((${arr[@]/%/+}0))"
42
$ VAR="$VAR -14"
$ arr=( $VAR );echo "$((${arr[@]/%/+}0))"
28
$
Run Code Online (Sandbox Code Playgroud)
小智 7
您的源字符串包含重复空格和前导/尾随空格。
\n\n将空格简单地转换为+
将会失败:
$ value=\' 2 1 34 3 2 \'\n$ echo "${value// /+}"\n++++++2+1++34+3++++2++++\n
Run Code Online (Sandbox Code Playgroud)\n\n折叠所有重复的空格并删除前导/尾随空格,您只需要对未加引号的变量使用 echo(或 printf)(假设 IFS 是默认值):
\n\nvalue=$(echo $value)\necho "${value// /+}"\n2+1+34+3+2\n
Run Code Online (Sandbox Code Playgroud)\n\n这可以提供给 bc:
\n\n$ echo "${value// /+}" | bc\n42\n
Run Code Online (Sandbox Code Playgroud)\n\n如果你想要的话,一切都在一行中:
\n\nvalue=$(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\'\n++++++2+1++34+3++++2++++\n
Run Code Online (Sandbox Code Playgroud)\n\n从 4.4 版开始就在 bash 上。在以前的版本中,它的工作原理如下:
\n\n~/bin/b43sh -c \'value=" 2 1 34 3 2 ";sed "s/ /+/g" <<<$value\'\n2+1+34+3+2\n
Run Code Online (Sandbox Code Playgroud)\n\n对于任何版本的 bash(和 sed),我们都可以做(一个相当强大的版本,但调用外部实用程序 -sed
):
sed "s/ \\+/+/g" <<<"0 $value 0" | tee /dev/tty | bc\n0+2+1+34+3+2+0\n42\n
Run Code Online (Sandbox Code Playgroud)\n\n纯 shell 解决方案(需要 bash、ksh 或 zsh 来替换${//}
部分)可能是:
value=$(echo $value); bc <<<"${value// /+}
以及更强大的(强制执行您的假设\xe2\x84\xa2)和可移植的版本:
\n\n(\xe2\x80\xa6)
。*
等(set -f)。+
(IFS=+) 连接。( IFS=" "; set -f; set -- $value; IFS=+; echo "$*" | bc; )
函数版本
\n 1- 如果您的 shell 不允许local
,请使用较慢的子 shell 形式
\n 2- 有些(在 POSIX 中正确)可能会抱怨使用不带引号的$*
.
sum(){ local IFS=" "; set -f; set -- $*; IFS=+; echo "$*" | bc; }
它以多种方式添加参数
\n\n$ value=" 2 1 34 3 2 "\n$ sum "$value"\n42\n$ sum $value # beware of glob chars *, ? and [ and of odd IFS=123 settings\n42\n$ sum " 2 1 34 3 2 "\n42\n$ sum " 2" "1 " "34 3" " 2 "\n42\n$ var=23\n$ sum " 2" "1 " "34 3" " 2 " "$var"\n65\n
Run Code Online (Sandbox Code Playgroud)\n