shell 数学是否在子 shell 中运行?

shell 数学是否在子 shell 中运行?

当我在 中执行简单的数学运算时#!/bin/sh,是否会创建一个子 shell?

例如,

addition=$(( 1 + 1 ))

语法会建议使用子 shell,但我找不到任何相关内容

答案1

$(cmd arg)在子 shell 环境中运行cmd,其输出(减去尾随换行符)成为扩展的结果。

(cmd arg)确实在子 shell 中运行,其输出不受影响。

所以与额外的子壳层$((cmd arg))相同,但它不是。$(cmd arg)

$((...))是来自 Korn shell 的一种单独的扩展形式。在 Korn shell 中,((arithmetic expression))计算算术表达式(其语法与 C 的语法非常相似),退出状态反映表达式是否解析为 0 还是非零。

这允许这样的事情:

if ((var < 10)); then
  ...
fi

这使得它看起来非常相似C

$用于介绍扩展。就像$(cmd)是一样,(cmd)除了它扩大的输出cmd$((arith))就像((arith))除了它扩大算术表达式的求值结果。

POSIX,其sh主要基于 ksh88,指定$((...))但未指定((...))。实际上,在早期的草案中,它是为$[...]相反,这就是为什么你发现它bashzsh支持$[...]作为 的替代品$((...))

IIRC,POSIX 最初考虑将其指定为的主要原因$[...]是因为与命令替换内的子 shell$((...))冲突。$((cmd arg))

您会发现大多数 shell 都正确识别$((echo x; echo y) | (tr xy ab))不是算术展开式,但不是$((cmd arg)).无论如何,$((cmd))都意味着扩展到$cmd变量的算术值,而不是扩展到 的输出cmd

POSIX规范中的相关文字有:

shell 命令语言的语法对于以“$((”开头的扩展存在歧义,它可以引入算术扩展或以子 shell 开头的命令替换。算术扩展具有优先权;也就是说,shell 应首先确定是否它可以将扩展解析为算术扩展,并且如果确定它无法将扩展解析为算术扩展,则仅当遇到结束时,shell 不需要评估嵌套扩展。如果尚未确定无法将扩展解析为算术扩展,则 shell 应将扩展视为不完整的算术扩展并报告语法错误。符合要求的应用程序应确保它将“$(”和 '( 分开。 ' 在以子 shell 开头的命令替换中分成两个标记(即,用空格分隔它们),例如,包含单个子 shell 的命令替换可以写为:

ksh((...))与嵌套子 shell 冲突。虽然 POSIX 没有指定((...)),但它确实允许 ksh 的行为。

实际上,在嵌套子 shell 和/或 cmdsubst 时,应确保在括号之间包含空格:

echo "$( (...) )"
( (a; b) | (c;d) )

答案2

这是一个演示不是在子 shell 中运行:您可以修改算术表达式中的变量:

$ x=5; echo "$(( x *= 2 ))"; echo "$x"
10
10

如果它是一个子 shell,echo $x将输出5.

使用 shell 算术时,请注意并非所有 shell 都支持前后自增; (当前版本的 Debian 及其衍生版本中的dash默认值)将解释为而不是递增变量。/bin/sh$(( ++i ))$(( +(+i) ))i

相关内容