Contents

如何计算Bash中的算术表达式

1.概述

计算数字在我们的bash脚本中通常很有用。然而,这个过程并不总是直截了当的。 在本教程中,我们将学习一些在bash中进行算术运算的方法。

2. bash中的变量

** bash没有类型系统——所有变量都是字符串。**出于这个原因,我们不能像用几乎任何其他语言那样简单地编写算术运算。默认情况下,它们将被解释为对字符串而不是数字的操作。

2.1. 声明变量

让我们首先使用不带任何属性的declare命令声明一个变量:

$ declare A=2+2
$ echo $A
2+2

正如我们所见,基于字符串的类型系统将其视为某些文本的声明。

2.2. 整数属性

如果我们希望这个表达式被解释为算术,我们需要明确地说明这一点。一种方法是使用*-i*属性声明变量:

$ declare -i A=2+2
$ echo $A
4

我们不应该忘记变量仍然是一个字符串。-i标志表明任何表达式在分配给该变量时都将被解析为整数。 如果存在解析错误,则结果将默认为零。同样,它将删除数字的任何小数部分:

$ A=test
$ echo $A
0

2.3. let命令

或者,let命令允许我们声明一个变量并在赋值期间执行算术运算。这里的区别是变量可以稍后重新分配给整数以外的东西:

$ let A=2+2
$ echo $A
4
$ A=test
$ echo $A
test

3. 参数扩展

现在我们已经创建了变量,我们需要一种方法来访问它们的值。此外,有时我们希望在没有声明的情况下即时获取表达式的值。

**参数扩展 允许我们用它的值替换一个表达式。**我们使用它从变量中获取值、调用命令和执行算术运算。

3.1.变量替换

我们可以使用美元符号 ($) 访问变量的值:

$ A=2
$ echo $A
2

我们还可以使用花括号将变量名称与表达式的其余部分分开:

$ echo ${A}string
2string

3.2. 算术展开

我们可以通过将其放在双括号中来获得算术运算的值,而无需将其声明为变量:

$ A=2;B=2
$ echo $((A+B+1))
5

3.3. 计数线示例

为了充分利用这些知识,让我们编写一个脚本,该脚本将打印文件的内容,其中行号位于左侧。

我们将首先声明一个输入变量和一个行计数器变量:

declare input=$1
declare -i counter=1

然后,我们将向行号添加填充以确保其长度是恒定的。为了实现这一点,我们将使用wc命令计算文件中的行数,然后检查结果数字的长度以显示填充大小:

declare -i lines=`wc -l < $input`
declare -i pad=${#lines}

在这里,我们通过将命令括在反引号中来将wc命令的结果存储在行内。然后,我们通过使用*${}语法的参数扩展和行前的哈希运算符#来分配pad*,它返回其值的长度。

现在,我们需要遍历文件的行,用填充打印计数器,然后打印行。最后,我们将在算术扩展中使用递增运算符 (++) 递增计数器:

while IFS= read -r line
do
  printf "%+${pad}s" $counter
  echo "| $line"
  ((counter++))
done < "$input"

这是完整的脚本:

#!/bin/bash
declare input=$1
declare -i counter=1
declare -i lines=`wc -l < $input`
declare -i pad=${#lines}
while IFS= read line
do
  printf "%+${pad}s" $counter
  echo "| $line"
  ((counter++))
done < "$input"

让我们通过运行它的前四行来尝试它。首先,我们将前四行重定向到一个临时文件:

$ head -4 lines_padding.sh > tmp

然后运行脚本:

$ ./lines_padding.sh tmp
1| #!/bin/sh
2| declare input=$1
3| declare -i counter=1
4| declare -i lines=`wc -l < $input`

4. expr命令

我们可以使用外部*expr 命令,而不是使用bash*的内置功能。它不是完成这项工作的最强大的程序,但它被广泛使用。此外,它是POSIX 标准的一部分。** expr除了解析布尔表达式之外还解析算术表达式。**它甚至可以对字符串执行一些匹配和子串操作:

$ expr 2 + 3
5
$ expr 2 \< 3
1
$ expr substr Blogdemo 1 4
Bael

我们应该注意,许多像“<”这样的字符需要转义。使用内置bash功能时不需要转义。此外,expr的 BSD/macOS 版本仅限于算术和布尔运算。

5. bc命令

bc 命令与expr类似, 但功能更强大。它也是 POSIX 标准的一部分。**最重要的是,bc允许浮点运算。**此外,它使用更广泛的运算符并提供简单的脚本语言。

5.1. 浮点运算

如果我们定义一个刻度(小数点后的最大位数),我们可以执行任意精度的浮点运算:

$ echo "scale=2;4/3" | bc
1.33

5.2. 脚本功能

bc还可以解析一种简单的、类似 C 的脚本语言,它允许我们声明变量、编写循环和编写条件语句。让我们编写一个脚本来打印从 1 到 10 的偶数:

$ echo "for(i=1; i<=10; i++) {if (i % 2 == 0) i;}" | bc
2
4
6
8
10

5.3. 内置函数

还有一些内置的数学函数。例如,我们可以得到十的平方根,比例为四:

$ echo "scale=4;sqrt(10)" | bc
3.1622