为什么我需要将“do”与“for”放在同一行?

Саш*_*ных 28 bash shell-script

一、总结

我不明白,为什么我需要E010 bashate rule


2. 详情

我使用bashate来检查.sh文件。E010 规则:

这样做不是在同一行

for 抨击:

是否有任何有效的论点,为什么我需要fordo在同一行?


3.没用

我在以下位置找不到我的问题的答案:

  1. 谷歌
  2. 关于最佳编码实践的文章(示例
  3. bashate 文档。我发现只有

    一组有助于在控制块中保持一致的规则。这些在有延续的长行中被忽略,因为展开有点“有趣”

Kus*_*nda 61

在语法上,以下两个代码片段是正确且等效的:

for f in bash/*.sh; do
    sashacommand "$f"
done
Run Code Online (Sandbox Code Playgroud)
for f in bash/*.sh
    do sashacommand "$f"
done
Run Code Online (Sandbox Code Playgroud)

后者可以可能说是难以阅读如do在循环体略微混淆的指令。如果循环包含多个命令并且下一个命令在新行上,混淆将进一步突出显示:

for f in *
    do cmd1
    cmd2
done
Run Code Online (Sandbox Code Playgroud)

...但将其标记为“错误”是恕我直言某人的个人意见,而不是客观事实。

我想说的是,如果你想在循环中添加命令do,那么如果这使得代码在阅读代码的人眼中保持一致和可读,那么可以随意这样做。

一般来说,几乎所有的;都可以用换行符代替。这两个;和换行符是命令终结。do是一个关键字,意思是“下面是需要做的事情(在这个for循环中)”。

for f in *; do ...; done
Run Code Online (Sandbox Code Playgroud)

是相同的

for f in *
do
   ...
done
Run Code Online (Sandbox Code Playgroud)

并作为

for f in *; do
   ...
done
Run Code Online (Sandbox Code Playgroud)

for f in *
   do ...
done
Run Code Online (Sandbox Code Playgroud)

使用一个的原因是可读性和本地/个人风格约定。


个人意见:

很长的循环标题中,我认为do换行可能是有意义的,如

for i in animals people houses thoughts basketballs bees
do
    ...
done
Run Code Online (Sandbox Code Playgroud)

或者

for i in        \
    animals     \
    people      \
    houses      \
    thoughts    \
    basketballs \
    bees
do
    ...
done
Run Code Online (Sandbox Code Playgroud)

这同样适用于将thenif声明。

但同样,这归结为一个人的个人风格偏好,或者一个人的团队/项目使用的任何编码风格。

  • @Barmar,请注意这里的问题使用了“need to”和“rule”之类的措辞,并且 bashate 自述文件将 `do` 放在单独的行上称为“错误”。这些都是比较严格的用语,所以似乎值得指出,恰恰相反,所谓的“规则”实际上只是一种主观意见。 (4认同)
  • @KonradRudolph 我的终端宽 80 个字符。如果列表换行,我将使它成为一组连续的行(如我的上一个示例),如果它_几乎_换行,我会将`do`(或`then`)单独放在一行上(如在倒数第二个例子)。这一切都与个人喜好有关。我不喜欢过长的行,部分原因是我的终端“只有”80 个字符宽,部分原因是我认为它看起来不整洁。我还发现很难解析很长的错误行。 (3认同)
  • @mtraceur 是的,我不是在质疑个人喜好。但请注意,您引用的可读性列限制不适用于代码。它只适用于散文。阅读代码的眼动根本不同,因此这些研究的证据在这里不适用。至于使用不再适用的历史原因作为基本原理,我们还使用了过去的 8.3 文件名。 (2认同)

ilk*_*chu 29

请注意页面顶部的内容:

bashate:bash 脚本的 pep8 等价物

PEP8是 Python 代码的风格指南。虽然 Python 人员似乎经常非常认真地对待他们的风格问题[需要引用],但这只是一个指南。我们可以想出将 与 放在do同一行for以及将其放在自己的行中的好处。

这与{在启动iforwhile块(或诸如此类)时将in C 代码放在何处的讨论相同。


在文档下面的几行中,还有另一个有趣的规则:

E020: 函数声明格式不正确 ^function name {$

我假设这里的要点是该样式指南的作者认为使用function关键字对于读者识别函数声明是必要的。但是,function foo是一个非标准定义一个函数的方式:所述标准方法是foo()。两者之间的唯一区别(在 Bash 中)是另一个更难移植到标准 shell,如/bin/sh在 Debian 或 Ubuntu 中。

因此,我建议您在所有此类风格指南中加一点盐或三粒盐,并自行决定最佳风格是什么。一个好的样式检查器允许禁用一些检查(bashate 必须bashate -i E010,E011忽略这两个检查。)一个优秀的样式检查器将允许您修改测试,例如在这里检查 E020 的反面。


ale*_*xis 13

TL;DR:你不需要。这只是一些老兄的意见。

像许多其他人一样,我for几十年来一直在写这样的循环:

for F in arg1 arg2 arg*
do
    somecommand "$F"
done
Run Code Online (Sandbox Code Playgroud)

这种布局突出了do ... done循环主体周围的事实,就像 C 类语言中的花括号一样,并允许换行符分隔循环结构的组件。

当然,关于花括号的放置位置也存在宗教战争,所以你可能会说陪审团仍然在这个问题上。恕我直言,这显然是它的设计方式;Bourne 喜欢匹配的分隔符,参见。if ... fi, case ... esac, 并且在较短的版本中需要分号表明您使它比最初设计的更短。没有错; 技术进步和许多曾经看起来是个好主意的东西现在不受欢迎,例如goto。但是,在整个 shell 脚本社区采用bashate作者的偏好之前,您不必做任何事情。

  • 对应于 `if` 和 `esac` 等的 `fi` 来自 Algol 68。 `for` 循环的 `do` 没有以 `od` 结束的唯一原因是 `od` 是名称现有的标准实用程序。见 https://en.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix (4认同)
  • 没听说过关于 `od` 的故事,这很有趣......(虽然,为什么不直接用 `rof` 结束 for 循环呢?) (2认同)
  • @alexis 好吧,就像 Kusalananda 说的,它来自 Algol 68,这是关键点。原始 Bourne shell 的创建者 Stephen Bourne 深受这种语言的影响,这就是他坚持使用这种语法的原因。即使他是用 C 编写的。请参阅 bourne shell 的源代码:https://minnie.tuhs.org//cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h哦,顺便说一下,`BEGIN` 和 `END` 也在那里定义。 (2认同)