【问题标题】:Bash c-style if statement and styling techniquesBash c 风格的 if 语句和样式技术
【发布时间】:2011-02-21 00:11:15
【问题描述】:

据我了解,您可以在 bash 中执行 C 风格的 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 看起来真的很奇怪。可维护性和标准很重要。

【问题讨论】:

  • 如果你想用 C 就用 C。但不要用 csh。
  • 除了 bash 之外,您还可以使用多种语言。如果你想要括号,Perl 可能适合你。但是IMO,编程语言中根本不需要括号。其他包括 Python 和 Ruby。 IMO,这两个有更“干净”的语法。
  • [] 被称为“方括号”(或“方括号”); {} 是大括号(或“花括号”或“花括号”); () 是括号(也称为“方括号”、“圆括号”和“括号”)。 C 对代码块使用大括号,对数组使用括号。

标签: bash if-statement


【解决方案1】:

bash(可能还有sh 系列的其他shell)有一些与if 相关的语法特性:

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

    • condition-command 可以是 bash 支持的任何命令(我认为甚至是另一个 if),然后执行并评估返回值。 (其实也可以是一个命令列表,不过这可能会混淆读者,最后一个命令的返回值算条件。)
    • Bash(和一般的 Unix shell)以一种有点不寻常的方式解释程序的结果代码(对于 C 程序员):结果 0 被解释为真(或“无错误”),任何其他结果被解释为false(或“发生了一些错误”)。 (在 C 和其他一些语言中,情况正好相反:0 是 false,其他的都是 true。)
    • 如果条件命令的结果为0(真),则执行listif的返回值是列表的结果)。如果它不是-0(假),则不执行列表(但elifelse 分支,如果有的话)。 (如果没有执行任何列表,则 if 的返回值为 0。)
  • 一些有用的命令作为条件(这些也可以作为while loops中的条件):

    • [ ... ] 实际上是编写test ... 的另一种方式 - 这只是一个命令,根据您提供的参数,它可能返回 0(真)或 1(假)。 (这是 shell 的构建。)
    • [[ ... ]] 是一个条件表达式命令。它支持 [ 支持的一些相同参数,以及更多,如括号、&lt;&gt;( ... ) 用于条件嵌套,并处理稍微不同的内部扩展,因为它是一种特殊的语法结构,而不是内置命令。整个过程是一个返回 0(真)或 1(假)的命令。
    • (( ... )) 是算术表达式(或其中几个)作为命令的包装器。当(最后)表达式的结果为非 0 时,结果为 0(真),当(最后)表达式的结果为 0 时,结果为 1(假)。(您可以改写为let ...。)

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

      • 一元:++--+-!~(类似于 C 语言)
      • 二进制算术:**(指数),*/%+-
      • 位移:&lt;&lt;&gt;&gt;
      • 比较:&lt;=&gt;=&lt;&gt;==!=(我认为这些返回 1(真)或 0(假))
      • 按位:&amp;^|
      • 逻辑:&amp;&amp;||,当然还有三元运算符:... ? ... : ...
      • 赋值:=,*=,/=,%=,+=,-=,&lt;&lt;=,&gt;&gt;=,&amp;=,&amp;=,@98764534
      • 逗号:,(简单连接两个表达式,返回最后一个的值)

      我认为总的来说,这很像 C 整数表达式。 (这些大致是按优先顺序排列的,但有时每个组内部都有划分。详情请查看info '(bash)Shell Arithmetic'。)

    • true 是一个什么都不做并且总是返回 0 的 buildin。
    • false 是一个什么都不做并且总是返回 1 的 buildin。
    • 您也可以将外部 C(或任何其他)程序称为命令,它们的返回值以相同的方式解释。
  • 列表:

    • ( ... ) 是一个命令列表,在子shell 中执行。此子 shell 中的变量分配不会向后传播。
    • { ...; } 是一个命令列表,它不会创建子 shell。
    • ; 是列表中命令的简单分隔符,但也可以替换为换行符。
    • &amp;&amp; 是仅当第一个返回 0 时执行第二个命令的分隔符。
    • || 是仅当第一个返回非 0 时执行第二个命令的分隔符。
    • &amp; 是命令的分隔符,并行执行两个命令(第一个在后台)。

所以,你可以用一些大括号和括号编写你的if-命令,但你仍然需要你的thenfi

if (( i > 0 ))
then {
   echo "i > 0"
}
else {
   echo "i <= 0"
}
fi

这里的大括号是多余的,因为thenelsefi 之间的命令无论如何都是(每个)一个列表。 (还要注意这里需要在右大括号之后和之前添加换行符或;。)

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

【讨论】:

  • 哇,感谢所有的描述!我也知道 then{ } else{} fi 语法的想法。
  • 我没有反对 bash 的语法。所有语法都需要时间来适应。我真的只是对所有 []、[[]]、{}、$() 和 (()) 业务感到困惑。它最初看起来非常丑陋,而且显然没有用。该列表确实有帮助,但您能否澄清 (( ... )) 语法。 “1(假)”应该是什么意思?
  • 这些 then 和 else 块中的大括号只是多余的,因为这些块的内容无论如何都被评估为列表。 – Bash(和一般的 unix shell)以一种不寻常的方式(对于 C 程序员)解释程序的结果代码:结果 0 被解释为true(或“无错误”),任何其他结果被解释为false(或“发生了一些错误”)。因此,我在这些数字的括号中添加了真或假,以避免混淆。 (((...))的澄清明天来,我现在该睡觉了。)
  • 这是有道理的。 :) 在 c 程序中,您返回 0 表示没有错误。它只是在 javascript 中,0(和空字符串)在表达式中表示 false,而任何其他值为 true。我希望有人标准化所有这些语法差异。
  • 所以,我添加了更多关于算术表达式的内容(并在答案中加入了我的最后一条评论)。
【解决方案2】:

在 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,是否有括号只是语言设计方面的考虑,如果我可以选择,我个人不会想要括号。

【讨论】:

  • Bash 使用双括号进行数字比较:a=3; if (( a &gt; b )); then ....
【解决方案3】:

当前语法的原因主要是历史原因。您所询问的大部分内容都基于原始的 Bourne shell (sh)。 Bourne 选择将语法基于 Algol 而不是 C。

要想拥有更类似于 C 的语法(和 not be csh),就必须从头开始。

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

您可能想查看Tiny C Compiler,它可用于将 C 源代码作为 shell 脚本运行。

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

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

【讨论】:

    【解决方案4】:

    使用 &amp;&amp;|| command lists花括号 group commands

    在以下示例中,truefalsetest 0 -eq 0 可以替换为 any 命令,包括像 (( i &gt; 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"
    

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

    【讨论】:

      【解决方案5】:

      如果您由于某种原因没有特别依赖 bash,我会鼓励您使用更现代的结构化脚本语言,例如 Ruby、Python 或 PHP,并简单地使用适当的脚本头来使它们可执行,例如一个 bash 脚本。我个人是控制台上 bash 单行代码的忠实拥护者,但发现它在用作脚本语言时完全是迟钝的。

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

      例如,您可以编写一个 Ruby 脚本并在其前面加上 #!/usr/bin/ruby,如下所示:

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

      【讨论】:

        猜你喜欢
        • 2020-10-28
        • 1970-01-01
        • 2021-01-26
        • 1970-01-01
        • 1970-01-01
        • 2019-04-29
        • 2013-12-11
        • 2011-03-14
        • 1970-01-01
        相关资源
        最近更新 更多