数字的绝对值

Absolute value of a number

我想在 bash 中通过以下代码获取数字的绝对值:

#!/bin/bash
echo "Enter the first file name: "
read first

echo "Enter the second file name: "
read second

s1=$(stat --format=%s "$first")
s2=$(stat -c '%s' "$second")

res= expr $s2 - $s1

if [ "$res" -lt 0 ]
then
        res=$res \* -1
fi

echo $res

现在我面临的问题是在 if 语句中,无论我如何更改它总是出现在 if 中,我尝试在语句周围放置 [[ ]] 但什么也没有。

这里是错误:

./p6.sh: line 13: [: : integer expression expected
$ s2=5 s1=4
$ echo $s2 $s1
5 4
$ res= expr $s2 - $s1
1
$ echo $res

第四行实际发生的是 res 被设置为空,并为 expr 命令导出。因此,当您 运行 [ "$res" -lt 0 ] res 扩展为空并且您看到错误时。

你可以只使用 arithmetic expression:

$ (( res=s2-s1 ))
$ echo $res
1

算术上下文保证结果将是一个整数,所以即使你所有的项一开始都是未定义的,你也会得到一个整数结果(即零)。

$ (( res = whoknows - whocares )); echo $res
0

或者,您可以通过这样声明来告诉 shell res 是一个整数:

$ declare -i res
$ res=s2-s1

这里有趣的是,赋值的右侧是在算术上下文中处理的,因此您不需要 $ 进行扩展。

你可能只需要 ${var#-}

${var#Pattern} Remove from $var the shortest part of $Pattern that matches the front end of $var. tdlp


示例:

s2=5; s1=4
s3=$((s1-s2))

echo $s3
-1

echo ${s3#-}
1

我知道这个线程在这一点上已经很老了,但我想分享我写的一个可以帮助解决这个问题的函数:

abs() { 
    [[ $[ $@ ] -lt 0 ]] && echo "$[ ($@) * -1 ]" || echo "$[ $@ ]"
}

这会将任何 mathematical/numeric 表达式作为参数,return 绝对值。例如:abs -4 => 4 或 abs 5-8 => 3

解决方法:尝试消除减号。

  1. sed
x=-12
x=$( sed "s/-//" <<< $x )
echo $x

12
  1. 检查第一个字符 parameter expansion
x=-12
[[ ${x:0:1} = '-' ]] && x=${x:1} || :
echo $x

12

此语法是 ternary opeartor. The colon ':' is the do-nothing 指令。

  1. 或将“-”符号替换为空(再次参数扩展)
x=-12
echo ${x/-/}

12

就个人而言,当我首先想到 string 时,编写脚本 bash 对我来说似乎更容易。

对于纯粹主义者,假设 bash 和一个相对较新的版本(我在 4.2 和 5.1 上测试过):

abs() {
  declare -i _value
  _value=
  (( _value < 0 )) && _value=$(( _value * -1 ))
  printf "%d\n" $_value
}

如果你不关心数学而只关心结果,你可以使用

echo $res | awk -F- '{print $NF}'

我将 this solution 翻译成 bash。我比公认的字符串操作方法或其他条件更喜欢它,因为它将 abs() 过程保留在数学部分

abs_x=$(( x * ((x>0) - (x<0)) ))

x=-3
abs_x= -3 * (0-1) = 3

x=4
abs_x= 4 * (1-0) = 4

最简单的解决方案:

res="${res/#-}"

如果 - 在第一个 # 字符处,则只删除一个 / 出现。