I have this bash script and I had a problem in line 16. How can I take the previous result of line 15 and add it to the variable in line 16?
我有这个bash脚本,在第16行有一个问题。如何将第15行之前的结果添加到第16行中的变量中?
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
num= $num + $metab (line16)
done
echo "$num"
done
10 个解决方案
#1
685
For integers:
整数:
-
Use arithmetic expansion:
$((EXPR))
使用算术扩张:$((EXPR))
num=$((num1 + num2)) num=$(($num1 + $num2)) # also works num=$((num1 + 2 + 3)) # ... num=$[num1+num2] # old, deprecated arithmetic expression syntax
-
Using the external
expr
utility. Note that this is only needed for really old systems.使用外部expr实用程序。注意,这只需要真正的旧系统。
num=`expr $num1 + $num2` # whitespace for expr is important
For floating point:
浮点数:
Bash doesn't directly support this, but there's a couple of external tools you can use:
Bash并不直接支持这一点,但是有几个外部工具可以使用:
num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc) # whitespace for echo is important
You can also use scientific notation (e.g.: 2.5e+2
)
你也可以使用科学的符号(例如:2.5e+2)
Common pitfalls:
常见的陷阱:
-
When setting a variable, you cannot have whitespace on either side of
=
, otherwise it will force the shell to interpret the first word as the name of the application to run (eg:num=
ornum
)在设置变量时,在=的任何一侧都不能有空白,否则它将强制shell将第一个单词解释为运行的应用程序的名称(例如:num=或num)
num= 1
num =2
全国矿工工会num = 1 = 2
-
bc
andexpr
expect each number and operator as a separate argument, so whitespace is important. They cannot process arguments like3+
+4
.bc和expr希望每个数字和运算符作为一个单独的参数,因此空格是重要的。它们不能处理像3+ 4这样的参数。
num=`expr $num1+ $num2`
num = expr num1 + num2美元的
#2
81
Use the $(( ))
arithmetic expansion.
使用$(())算术扩展。
num=$(( $num + $metab ))
See http://tldp.org/LDP/abs/html/arithexp.html for more information.
请参阅http://tldp.org/LDP/abs/html/arithexp.html获取更多信息。
#3
24
There are a thousand and one ways to do it. Here's one using dc
:
有上千种方法可以做到这一点。这里有一个使用dc:
dc <<<"$num1 $num2 + p"
But if that's too bash-y for you (or portability matters) you could say
但如果这对你(或可移植性问题)来说太过分了,你可以说。
echo $num1 $num2 + p | dc
But maybe you're one of those people who thinks RPN is icky and weird; don't worry! bc
is here for you:
但也许你是那些认为RPN是恶心和怪异的人之一;别担心!bc在这里为你:
bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc
That said, there are a some unrelated improvements you could be making to your script
也就是说,你可以对脚本进行一些不相关的改进。
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in output-$i-* ; do # for can glob directly, no need to ls
echo "$j"
# grep can read files, no need to use cat
metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
num=$(( $num + $metab ))
done
echo "$num"
done
EDIT:
编辑:
As described in BASH FAQ 022, bash does not natively support floating point numbers. If you need to sum floating point numbers the use of an external tool (like bc
or dc
) is required.
正如BASH FAQ 022中所描述的,BASH并没有本机支持浮点数。如果需要对浮点数求和,则需要使用外部工具(如bc或dc)。
In this case the solution would be
在这种情况下,解是。
num=$(dc <<<"$num $metab + p")
To add accumulate possibly-floating-point numbers into num
.
将可能的浮点数添加到num中。
#4
21
In bash,
在bash中,
num=5
x=6
(( num += x ))
echo $num # ==> 11
Note that bash can only handle integer arithmetic, so if your awk command returns a fraction, then you'll want to redesign: here's your code rewritten a bit to do all math in awk.
注意,bash只能处理整数算术,因此,如果awk命令返回一个分数,那么您将需要重新设计:这是您的代码重写了一点,以便在awk中完成所有的计算。
num=0
for ((i=1; i<=2; i++)); do
for j in output-$i-*; do
echo "$j"
num=$(
awk -v n="$num" '
/EndBuffer/ {sum += $2}
END {print n + (sum/120)}
' "$j"
)
done
echo "$num"
done
#5
14
I really like this method as well, less clutter:
我真的很喜欢这个方法,更少的杂乱:
count=$[count+1]
#6
14
I always forget the syntax so I come to google, but then I never find the one I'm familiar with :P. This is the cleanest to me and more true to what I'd expect in other languages.
我总是忘记语法,所以我来到谷歌,但是我从来没有找到我熟悉的那个:P。这对我来说是最干净的,更符合我对其他语言的期望。
i=0
((i++))
echo $i;
#7
4
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
#8
4
You should declare metab as integer and then use arithmetic evaluation
您应该将metab声明为整数,然后使用算术评估。
declare -i metab num
...
num+=metab
...
For more information see https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic
有关更多信息,请参见https://www.gnu.org/software/bash/manual/html_node/shell-math .html# shell -算术。
#9
2
Another portable POSIX
compliant way to do in bash
, which can be defined as a function in .bashrc
for all the arithmetic operators of convenience.
bash中的另一种可移植的POSIX兼容方法,它可以定义为.bashrc中的一个函数,用于所有方便的算术运算符。
addNumbers () {
local IFS='+'
printf "%s\n" "$(( $* ))"
}
and just call it in command-line as,
在命令行中调用它,
addNumbers 1 2 3 4 5 100
115
The idea is to use the Input-Field-Separator(IFS), a special variable in bash
used for word splitting after expansion and to split lines into words. The function changes the value locally to use word-splitting character as the sum operator +
.
这个想法是使用输入-字段分隔符(IFS),在bash中一个特殊的变量用于在扩展后的单词分割,并将行分割成单词。该函数在本地更改值,以使用单词拆分字符作为sum运算符+。
Remember the IFS
is changed locally and does NOT take effect on the default IFS
behaviour outside the function scope. An excerpt from the man bash
page,
请记住,IFS是在本地更改的,并且不会对函数范围之外的默认IFS行为生效。摘自男人的bash页面,
The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly , the default, then sequences of , , and at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words.
shell将IFS的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符的单词。如果IFS是未设置的,或者它的值是正确的,那么默认的,然后是序列的,并且在前面的扩展的结果的开始和结束都被忽略了,并且任何一个IFS字符的序列在开始或结束时都不能用来分隔单词。
The "$(( $* ))"
represents the list of arguments passed to be split by +
and later the sum value is output using the printf
function. The function can be extended to add scope for other arithmetic operations also.
“$(($*))”表示由+分配的参数列表,然后使用printf函数输出sum值。该函数还可以扩展到其他算术运算的范围。
#10
0
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
let num=num+metab (line 16)
done
echo "$num"
done
#1
685
For integers:
整数:
-
Use arithmetic expansion:
$((EXPR))
使用算术扩张:$((EXPR))
num=$((num1 + num2)) num=$(($num1 + $num2)) # also works num=$((num1 + 2 + 3)) # ... num=$[num1+num2] # old, deprecated arithmetic expression syntax
-
Using the external
expr
utility. Note that this is only needed for really old systems.使用外部expr实用程序。注意,这只需要真正的旧系统。
num=`expr $num1 + $num2` # whitespace for expr is important
For floating point:
浮点数:
Bash doesn't directly support this, but there's a couple of external tools you can use:
Bash并不直接支持这一点,但是有几个外部工具可以使用:
num=$(awk "BEGIN {print $num1+$num2; exit}")
num=$(python -c "print $num1+$num2")
num=$(perl -e "print $num1+$num2")
num=$(echo $num1 + $num2 | bc) # whitespace for echo is important
You can also use scientific notation (e.g.: 2.5e+2
)
你也可以使用科学的符号(例如:2.5e+2)
Common pitfalls:
常见的陷阱:
-
When setting a variable, you cannot have whitespace on either side of
=
, otherwise it will force the shell to interpret the first word as the name of the application to run (eg:num=
ornum
)在设置变量时,在=的任何一侧都不能有空白,否则它将强制shell将第一个单词解释为运行的应用程序的名称(例如:num=或num)
num= 1
num =2
全国矿工工会num = 1 = 2
-
bc
andexpr
expect each number and operator as a separate argument, so whitespace is important. They cannot process arguments like3+
+4
.bc和expr希望每个数字和运算符作为一个单独的参数,因此空格是重要的。它们不能处理像3+ 4这样的参数。
num=`expr $num1+ $num2`
num = expr num1 + num2美元的
#2
81
Use the $(( ))
arithmetic expansion.
使用$(())算术扩展。
num=$(( $num + $metab ))
See http://tldp.org/LDP/abs/html/arithexp.html for more information.
请参阅http://tldp.org/LDP/abs/html/arithexp.html获取更多信息。
#3
24
There are a thousand and one ways to do it. Here's one using dc
:
有上千种方法可以做到这一点。这里有一个使用dc:
dc <<<"$num1 $num2 + p"
But if that's too bash-y for you (or portability matters) you could say
但如果这对你(或可移植性问题)来说太过分了,你可以说。
echo $num1 $num2 + p | dc
But maybe you're one of those people who thinks RPN is icky and weird; don't worry! bc
is here for you:
但也许你是那些认为RPN是恶心和怪异的人之一;别担心!bc在这里为你:
bc <<< "$num1 + $num2"
echo $num1 + $num2 | bc
That said, there are a some unrelated improvements you could be making to your script
也就是说,你可以对脚本进行一些不相关的改进。
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in output-$i-* ; do # for can glob directly, no need to ls
echo "$j"
# grep can read files, no need to use cat
metab=$(grep EndBuffer "$j" | awk '{sum+=$2} END { print sum/120}')
num=$(( $num + $metab ))
done
echo "$num"
done
EDIT:
编辑:
As described in BASH FAQ 022, bash does not natively support floating point numbers. If you need to sum floating point numbers the use of an external tool (like bc
or dc
) is required.
正如BASH FAQ 022中所描述的,BASH并没有本机支持浮点数。如果需要对浮点数求和,则需要使用外部工具(如bc或dc)。
In this case the solution would be
在这种情况下,解是。
num=$(dc <<<"$num $metab + p")
To add accumulate possibly-floating-point numbers into num
.
将可能的浮点数添加到num中。
#4
21
In bash,
在bash中,
num=5
x=6
(( num += x ))
echo $num # ==> 11
Note that bash can only handle integer arithmetic, so if your awk command returns a fraction, then you'll want to redesign: here's your code rewritten a bit to do all math in awk.
注意,bash只能处理整数算术,因此,如果awk命令返回一个分数,那么您将需要重新设计:这是您的代码重写了一点,以便在awk中完成所有的计算。
num=0
for ((i=1; i<=2; i++)); do
for j in output-$i-*; do
echo "$j"
num=$(
awk -v n="$num" '
/EndBuffer/ {sum += $2}
END {print n + (sum/120)}
' "$j"
)
done
echo "$num"
done
#5
14
I really like this method as well, less clutter:
我真的很喜欢这个方法,更少的杂乱:
count=$[count+1]
#6
14
I always forget the syntax so I come to google, but then I never find the one I'm familiar with :P. This is the cleanest to me and more true to what I'd expect in other languages.
我总是忘记语法,所以我来到谷歌,但是我从来没有找到我熟悉的那个:P。这对我来说是最干净的,更符合我对其他语言的期望。
i=0
((i++))
echo $i;
#7
4
#!/bin/bash
read X
read Y
echo "$(($X+$Y))"
#8
4
You should declare metab as integer and then use arithmetic evaluation
您应该将metab声明为整数,然后使用算术评估。
declare -i metab num
...
num+=metab
...
For more information see https://www.gnu.org/software/bash/manual/html_node/Shell-Arithmetic.html#Shell-Arithmetic
有关更多信息,请参见https://www.gnu.org/software/bash/manual/html_node/shell-math .html# shell -算术。
#9
2
Another portable POSIX
compliant way to do in bash
, which can be defined as a function in .bashrc
for all the arithmetic operators of convenience.
bash中的另一种可移植的POSIX兼容方法,它可以定义为.bashrc中的一个函数,用于所有方便的算术运算符。
addNumbers () {
local IFS='+'
printf "%s\n" "$(( $* ))"
}
and just call it in command-line as,
在命令行中调用它,
addNumbers 1 2 3 4 5 100
115
The idea is to use the Input-Field-Separator(IFS), a special variable in bash
used for word splitting after expansion and to split lines into words. The function changes the value locally to use word-splitting character as the sum operator +
.
这个想法是使用输入-字段分隔符(IFS),在bash中一个特殊的变量用于在扩展后的单词分割,并将行分割成单词。该函数在本地更改值,以使用单词拆分字符作为sum运算符+。
Remember the IFS
is changed locally and does NOT take effect on the default IFS
behaviour outside the function scope. An excerpt from the man bash
page,
请记住,IFS是在本地更改的,并且不会对函数范围之外的默认IFS行为生效。摘自男人的bash页面,
The shell treats each character of IFS as a delimiter, and splits the results of the other expansions into words on these characters. If IFS is unset, or its value is exactly , the default, then sequences of , , and at the beginning and end of the results of the previous expansions are ignored, and any sequence of IFS characters not at the beginning or end serves to delimit words.
shell将IFS的每个字符视为分隔符,并将其他扩展的结果拆分为这些字符的单词。如果IFS是未设置的,或者它的值是正确的,那么默认的,然后是序列的,并且在前面的扩展的结果的开始和结束都被忽略了,并且任何一个IFS字符的序列在开始或结束时都不能用来分隔单词。
The "$(( $* ))"
represents the list of arguments passed to be split by +
and later the sum value is output using the printf
function. The function can be extended to add scope for other arithmetic operations also.
“$(($*))”表示由+分配的参数列表,然后使用printf函数输出sum值。该函数还可以扩展到其他算术运算的范围。
#10
0
#!/bin/bash
num=0
metab=0
for ((i=1; i<=2; i++)); do
for j in `ls output-$i-*`; do
echo "$j"
metab=$(cat $j|grep EndBuffer|awk '{sum+=$2} END { print sum/120}') (line15)
let num=num+metab (line 16)
done
echo "$num"
done