Bash c风格if语句和样式技巧

时间:2011-02-21 00:11:15

标签: bash if-statement

根据我的理解,你可以在bash中执行C-style for和while循环。

LIMIT=10

for ((a=1; a <= LIMIT ; a++))  # Double parentheses, and "LIMIT" with no "$".
do
  echo -n "$a "
done                           # A construct borrowed from 'ksh93'.

甚至是三元运营商。

(( var0 = var1<98?9:21 ))

您如何使用if声明执行此操作?

另外为什么他们不像C一样实施大括号呢?使用donedoiffi等所有关键字的逻辑是什么?我将编写一些脚本,但bash看起来非常不同。

是否有任何bash样式技术或bash替代品/插件?我想遵循标准,但来自C,Java和PHP背景bash看起来很奇怪。可维护性和标准很重要。

5 个答案:

答案 0 :(得分:12)

bash(和sh家族的其他shell)有一些与if有关的语法特性:

  • 基本if语句的语法为if condition-command ; then list ; fi(可以为其他分支添加elifelse。)

    • condition-command可以是bash支持的任何命令(我认为,即使是另一个命令),然后执行返回值。 (实际上,它也可以是一个命令列表,但这可能会使读者感到困惑。最后一个命令的返回值会计入条件。)
    • Bash(和一般的Unix shell)以一种不寻常的方式解释程序的结果代码(对于C程序员):0的结果被解释为true(或“无错误”),并且任何其他结果被解释为false(或“发生了一些错误”)。 (在C和其他一些语言中,它是相反的:0是false,其他一切都是true。)
    • 如果condition-command的结果为0(true),则执行listif的返回值是列表的结果)。如果它不是-0(假),则不执行列表(但elifelse分支(如果有)。 (如果没有执行任何列表,则if的返回值为0.)
  • 一些有用的命令作为条件(这些也可以作为while loops中的条件):

    • [ ... ]实际上是写test ...的另一种方式 - 这只是一个可能返回0(真)或1(假)的命令,具体取决于你给出的参数。 (这是shell的构建。)
    • [[ ... ]]是条件表达式命令。它支持[支持的一些相同的参数,还有一些,如括号,<>( ... )条件嵌套,并处理有点不同的扩展,因为它是一个特殊的语法结构而不是buildin命令。整个事情是一个返回0(真)或1(假)的命令。
    • (( ... ))是一个算术表达式(或其中几个)作为命令的包装器。当(last)表达式的结果为非0时,结果为0(true);当(last)表达式的结果为0时,结果为1(false)。(您可以改为写let ...。)

      在算术表达式中,shell变量可以在没有$的情况下使用,并且所有内容都被解释为整数(具有固定宽度,但我没有找到哪个)。您可以使用这些运算符:

      • 一元:++--+-!~(如C中所示)
      • 二进制算术:**(指数),*/%+-
      • 位移:<<>>
      • 比较:<=>=<>==!=(我认为这些返回1(真)或0(假))
      • 按位:&^|
      • 逻辑:&&||,当然还有三元运营商:... ? ... : ...
      • 作业:=*=/=%=+=-=<<=,{{1 }},>>=&=^=
      • 逗号:|=(只是连接两个表达式,返回最后一个的值)

      我认为一般来说这很像C整数表达式。 (这些大致按优先顺序排列,但有时每组内都有分歧。请查看,了解详细信息。)

    • info '(bash)Shell Arithmetic'是一个不做任何事情并且总是返回0的构建。
    • true是一个不做任何事情并且总是返回1的构建。
    • 您也可以将外部C(或其他任何)程序称为命令,其返回值的解释方式相同。
  • 解释

    • false是一个命令列表,在子shell中执行。此子shell中的变量赋值不会传播回来。
    • ( ... )是一个命令列表,它不会创建子shell。
    • { ...; }是列表中命令的简单分隔符,但也可以换成换行符。
    • ;是仅在第一个返回0时执行第二个命令的命令的分隔符。
    • &&是仅在第一个返回not-0时执行第二个命令的命令的分隔符。
    • ||是命令的分隔符,并行执行这两个命令(后台的第一个命令)。

所以,你可以用{括号和圆括号'来编写& - 命令,但仍然需要ifthen

fi

这里的括号简直是多余的,因为if (( i > 0 )) then { echo "i > 0" } else { echo "i <= 0" } fi thenelse之间的命令无论如何都是(每个)一个列表。 (另请注意在此处关闭括号之前和之前需要换行或fi。)

但正如其他人所说,如果你想使用类似C的语法,更好地使用另一种语言。

答案 1 :(得分:1)

在bash中,if语句没有像()这样的括号,例如bash中的某些语法

if [[ ... ]];then
  ..
fi 

if [ ... ];then
 ...
fi

if $(grep .. file) ;then  #note the () is part of $().
  ...
fi

我没有反对Bash,但IMO,你最好使用一种编程语言,它可以为你提供编写脚本/编程工作所需的所有东西,比如Python,Ruby或Perl。 Bash有一些局限性,比如执行浮点数学等。另外,如果你的任务很复杂,过度使用* nix工具可能会导致脚本“膨胀”,从而影响性能。如果你想要“干净”的语法和可维护性,Ruby / Python可能适合你。 IMO,有或没有括号只是语言设计考虑因素,如果我有选择,我个人不会想要括号。

答案 2 :(得分:1)

当前语法的原因主要是历史性的。你问的大多数都是基于最初的Bourne shell(sh)。 Bourne选择将语法基于Algol而不是C。

要拥有更像C的语法(和not be csh),有人必须从头开始。

正如其他人所说,出于多种目的,您可以用其他语言编写脚本。

您可能希望查看可用于将C源作为shell脚本运行的Tiny C Compiler

#!/usr/bin/tcc -run
#include <stdio.h>

int main()
{
    printf("Hello World\n");
    return 0;
}

答案 3 :(得分:1)

使用&&|| command lists弯括号 group commands

在下面的示例中,truefalsetest 0 -eq 0可以用 any 命令替换,包括(( i > 0 ))等算术表达式

多行样式

true && {
  echo "true command returns zero (aka success)"
  # more commands here
  # and here
} || {
  echo "true command never returns non-zero"
  # more commands here
  # and here
}

模糊的嵌入式样式

# I don't like this one so much
false && echo "false never returns zero" || echo "false returns always 1"

拆分内嵌样式

# here the draw-back are back slashes
test 0 -eq 0 \
  && echo "Surprise, zero is equal to zero" \
  || echo "Apocalypse is near if zero is not zero"

注意:我可以断言上述技术可以奏效,但是我不知道它们是否存在性能缺陷。

答案 4 :(得分:0)

如果由于某些原因你没有特别依赖bash,我会鼓励你使用更现代的结构化脚本语言,如Ruby,Python或PHP,并简单地使用适当的脚本头来使它们像一个bash脚本。我个人非常喜欢控制台上的bash one-liners,但是当它用作脚本语言时发现它完全是钝的。

大多数现代脚本语言都可以让您轻松访问类似ARGV的数组,以获取命令行参数,并支持熟悉的循环和控制结构。

因此,例如,您编写了一个Ruby脚本,并以#!/usr/bin/ruby为前缀,如下所示:

#!/usr/bin/ruby
for a in 1..10
  puts ( a >= 5 ) ? "a >= 5" : "a < 5"
end