Bash c-style if 语句和样式技术

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5061100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 23:29:44  来源:igfitidea点击:

Bash c-style if statement and styling techniques

bashif-statement

提问by Lime

From what I understand you can do C-style for and while loops in bash.

据我了解,您可以在 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'.

And even ternary operators.

甚至三元运算符。

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

How would you do this with the ifstatement?

你会如何用if声明来做到这一点?

Also why don't they implement braces like in C? What is the logic with using all of these keywords like done, do, if, and fi? I will be writing some scripts but bash appears very different.

另外他们为什么不像在 C 中那样实现大括号?什么是使用这些关键字,如逻辑donedoif,和fi?我将编写一些脚本,但 bash 看起来非常不同。

Are there any bash styling techniques or bash alternatives/plugins? I would like to follow the standard, but coming from a C, Java and PHP background bash looks really weird. Maintainability and standards are important.

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

回答by Pa?lo Ebermann

There are some syntactic specialties of bash (and maybe other shells of the shfamily) related to if:

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

  • The basic if-statement has the syntax if condition-command ; then list ; fi(with the possibility to add elifand elsefor other branches).

    • The condition-commandcan be any command that bash supports (even another if, I think), is executed and the return value is then evaluated. (Actually, it can also be a list of commands, but this might confuse readers. The return value of the last command counts for the condition.)
    • Bash (and Unix shells in general) interpret result codes of programs in a bit unusual way (for C programmers): a result of 0 is interpreted as true (or "no error"), and any other result is interpreted as false (or "some error occurred"). (In C and some other languages it is the other way around: 0 is falseand everything else is true.)
    • If the result of the condition-command is 0 (true), the listis executed (and the return value of the ifis the result of the list). If it is not-0 (false), the list is not executed (but the elifor elsebranches, if there are any). (If none of the lists is executed, the return value of the if is 0.)
  • Some useful commands as conditions (these work also as conditions in while loops):

    • [ ... ]is in fact another way to write test ...- this is simply a command which may return 0 (true) or 1 (false) depending on what parameters you are giving. (This is a buildin of the shell.)
    • [[ ... ]]is a conditional expression command. It supports some of the same arguments that [supports, and some more, like parentheses, <, >, and (... )for condition nesting, and handles expansions inside a bit different, since it is a special syntactic construct instead of a buildin command. The whole thing is a command that returns 0 (true) or 1 (false).
    • (( ... ))is a wrapper for an arithmetic expression (or several of them) as a command. The result is 0 (true) when the result of the (last) expression is non-0, and 1 (false) when the result of the (last) expression is 0. (You could instead write let ....)

      In arithmetic expressions the shell variables can be used without $, and everything is interpreted as integers (of a fixed width, but I didn't find out which). You can use these operators:

      • unary: ++, --, +, -, !, ~(like in C)
      • binary arithmetic: **(exponentation), *, /, %, +, -
      • bit-shift: <<, >>
      • comparison: <=, >=, <, >, ==, !=(I think these return either 1 (true) or 0 (false))
      • bitwise: &, ^, |
      • logical: &&, ||, and of course the ternary operator: ... ? ... : ...
      • assignment: =, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=, |=
      • comma: ,(simply connects two expressions, returning the value of the last one)

      I think in general this works a lot like C integer expressions. (These are roughly in order of precedence, but sometimes there are divisions inside of each group. Look in info '(bash)Shell Arithmetic'for details.)

    • trueis a buildin which does nothing and always returns 0.
    • falseis a buildin which does nothing and always returns 1.
    • you can also call your external C (or anything else) programs as commands, their return values are interpreted the same way.
  • Lists:

    • ( ... )is a list of commands, which is executed in a subshell. Variable assignments in this subshell are not propagated back.
    • { ...; }is a list of commands, which does not create a subshell.
    • ;is a simple separator of commands in a list, but can also be replaced by a new-line.
    • &&is a separator of commands executing the second one only when the first returned 0.
    • ||is a separator of commands executing the second one only when the first returned not-0.
    • &is a separator of commands, executing both commands in parallel (the first one in background).
  • 基本的 if 语句具有语法if condition-command ; then list ; fi(可以添加elifelse用于其他分支)。

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

    • [ ... ]实际上是另一种写法test ...- 这只是一个命令,它可能会返回 0(真)或 1(假),具体取决于您提供的参数。(这是外壳的构建。)
    • [[ ... ]]是条件表达式命令。它支持一些与支持相同的参数[,还有一些,例如括号、<>(...)用于条件嵌套,并且处理内部扩展有点不同,因为它是一个特殊的句法构造而不是内置命令。整个过程是一个返回 0(真)或 1(假)的命令。
    • (( ... ))是作为命令的算术表达式(或其中几个)的包装器。当(最后一个)表达式的结果为非 0 时,结果为 0(真),当(最后一个)表达式的结果为 0 时,结果为 1(假)let ...。(你可以改为写.)

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

      • 一元:++, --, +, -, !, ~(如在 C 中)
      • 二元算术:(**取幂), *, /, %, +,-
      • 位移:<<,>>
      • 比较:<=, >=, <, >, ==, !=(我认为这些返回 1(真)或 0(假))
      • 按位:&, ^,|
      • 逻辑:&&, ||,当然还有三元运算符:... ? ... : ...
      • 赋值:=, *=, /=, %=, +=, -=, <<=, >>=, &=, ^=,|=
      • 逗号:(,简单连接两个表达式,返回最后一个的值)

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

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

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

So, you canwrite your if-command with some braces and parentheses, but you still need your thenand fi:

所以,你可以if用一些大括号和括号写你的-command,但你仍然需要你的thenand fi

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

The braces here are simply superfluous, since the commands between then, elseand fiare (each) one list anyway. (Also note the need of new-lines or ;after and before the closing braces here.)

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

But as the others said, better use another language if you want to use a C-like syntax.

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

回答by kurumi

In bash, the if statement doesn't have brackets like ()eg of some syntax in bash

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

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

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

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

I have nothing against Bash, but IMO, you are better off using a programming language which can provide you all the things you need in your scripting/programming endeavor, such as Python, Ruby or Perl. Bash has some limitations, like performing floating points maths,etc.Also, if your task is complex enough, excessive use of *nix tools may lead to "bloatedness" of your script, hence hindering performance. If you want "clean" syntax and maintainability, either Ruby/Python may suit you. IMO, having brackets or not is just language design considerations and I personally would not want brackets if i have the choice.

我不反对 Bash,但是 IMO,您最好使用一种编程语言,它可以为您提供脚本/编程工作中所需的所有东西,例如 Python、Ruby 或 Perl。Bash 有一些限制,例如执行浮点数学等。此外,如果您的任务足够复杂,过度使用 *nix 工具可能会导致您的脚本“臃肿”,从而影响性能。如果您想要“干净”的语法和可维护性,Ruby/Python 都可能适合您。IMO,是否有括号只是语言设计方面的考虑,如果我有选择的话,我个人不会想要括号。

回答by Paused until further notice.

The reason for the current syntax is largely historical. Most of what you're asking about is based on the original Bourne shell (sh). Bourne chose to base the syntax on Algol instead of C.

当前语法的原因在很大程度上是历史性的。您所问的大部分内容都基于原始的 Bourne shell (sh)。Bourne 选择基于 Algol 而不是 C 的语法。

To have a more C-like syntax (and not be csh), someone would have to start from scratch.

要拥有更像 C 的语法(而不是 csh),必须有人从头开始。

As others have said, for many purposes you can write scripts in other languages.

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

You might want to look at Tiny C Compilerwhich can be used to run C source as a shell script.

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

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

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

回答by laconbass

Use &&and ||command listsand curly-bracedgroup commands

使用&&||命令列表花括号组命令

On examples below, true, false, or test 0 -eq 0could be replaced by anycommand, including arithmetic expressions like (( i > 0 ))

在下面的示例中,true, false, 或test 0 -eq 0可以被任何命令替换,包括算术表达式,例如(( i > 0 ))

Multi-linestyle

多线样式

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
}

Obfuscated in-linestyle

混淆的内联样式

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

Split in-linestyle

分割线样式

# 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"


NOTE: I can assert the techniques above work, but I don't know the performance drawbacks, if there are.

注意:我可以断言上述技术有效,但我不知道性能缺陷,如果有的话。

回答by Hyman Senechal

If you're not tied to bash in particular for some reason, I would encourage you to use a more modern structured scripting language such as Ruby, Python, or PHP, and simply use the appropriate script header to make them executable like a bash script. I personally am a huge fan of bash one-liners on the console, but find it to be completely obtuse when used as a scripting language.

如果由于某种原因您没有特别依赖于 bash,我鼓励您使用更现代的结构化脚本语言,例如 Ruby、Python 或 PHP,并且只需使用适当的脚本头来使它们像 bash 脚本一样可执行. 我个人是控制台上 bash one-liners 的忠实粉丝,但发现当用作脚本语言时,它是完全迟钝的。

Most modern scripting languages will give you easy access to an array like ARGVfor command line arguments, and support familiar loops and control structures.

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

So, for instance, you'd write a Ruby script and preface it with #!/usr/bin/ruby, like so:

因此,例如,您将编写一个 Ruby 脚本并以 开头#!/usr/bin/ruby,如下所示:

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