AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / unix / 问题 / 443507
Accepted
Саша Черных
Саша Черных
Asked: 2018-05-13 23:23:10 +0800 CST2018-05-13 23:23:10 +0800 CST 2018-05-13 23:23:10 +0800 CST

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

  • 772

一、总结

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


2. 细节

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

不要与for在同一行

for重击:

  • 正确的:

    #!/bin/bash
    for f in bash/*.sh; do
        sashacommand "$f"
    done
    
  • 错误:

    #!/bin/bash
    for f in bash/*.sh
        do sashacommand "$f"
    done
    

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


3. 没用

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

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

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

bash shell-script
  • 5 5 个回答
  • 6953 Views

5 个回答

  • Voted
  1. Best Answer
    Kusalananda
    2018-05-13T23:32:37+08:002018-05-13T23:32:37+08:00

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

    for f in bash/*.sh; do
        sashacommand "$f"
    done
    
    for f in bash/*.sh
        do sashacommand "$f"
    done
    

    可能会说后一个更难阅读,因为它do稍微混淆了循环体中的命令。如果循环包含多个命令并且下一个命令在新行上,则混淆将进一步突出显示:

    for f in *
        do cmd1
        cmd2
    done
    

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

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

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

    for f in *; do ...; done
    

    是相同的

    for f in *
    do
       ...
    done
    

    并作为

    for f in *; do
       ...
    done
    

    和

    for f in *
       do ...
    done
    

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


    个人观点:

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

    for i in animals people houses thoughts basketballs bees
    do
        ...
    done
    

    或者

    for i in        \
        animals     \
        people      \
        houses      \
        thoughts    \
        basketballs \
        bees
    do
        ...
    done
    

    theninif语句也是如此。

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

    • 62
  2. ilkkachu
    2018-05-14T00:59:08+08:002018-05-14T00:59:08+08:00

    请注意页面顶部的内容:

    bashate:bash 脚本的 pep8 等价物

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

    {这与启动if或while块(或类似)时将 C 代码放在何处的讨论相同。


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

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

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

    因此,我建议您将任何和所有此类风格指南都加一粒或三粒盐,然后自己决定最好的风格是什么。一个好的样式检查器允许禁用一些检查(bashate 必须bashate -i E010,E011忽略这两个检查。)一个优秀的样式检查器将允许您修改测试,例如检查 E020 的对立面,here。

    • 29
  3. alexis
    2018-05-14T06:47:55+08:002018-05-14T06:47:55+08:00

    TL;DR:你不需要。这只是一些小伙伴的意见。

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

    for F in arg1 arg2 arg*
    do
        somecommand "$F"
    done
    

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

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

    • 14
  4. user56373
    2018-05-15T16:35:46+08:002018-05-15T16:35:46+08:00

    这里有几个很好的答案。始终对风格指南持保留态度,恕我直言和经验,对于任何在风格方面充斥着过多教条的社区,都要稍微到中等程度地关注。几乎就像他们相信,当他们最终得到最后一个 I 点,并且最后一个 T 交叉时,软件就会工作。有时,消除错误需要的不仅仅是完美的风格......

    当我开始学习 shell 时,大多数脚本和教程都使用内联分号格式

    for i in "$@"; do
        stuff
    done
    

    但是由于我没有经验,所以我很难发现 ; 并且做 - 两者对于确认语法正确性都是必不可少的。所以我更喜欢下一行的 do 本身。我不再那样做了(双关语)

    此外,'while' 命令是一个不错的小技巧的绝佳候选者:

    while prep1; prep2; condition; do
        stuff
    done
    

    但是当准备命令有点庞大,和/或条件很复杂时,最好将其格式化为

    while
        prep1
        prep2
        condition
    do
        stuff
    done
    

    然后将do附加为“; do”是积极的。

    你甚至可以变得更激烈:

    while
        if con1; then
          cond2
        elif cond3; then
          cond4
        elif cond5; then
          cond6
        else
          cond7
        fi
    do
        stuff
    done
    

    因为每个语句都是一个表达式。注意这两种风格是如何投机取巧地使用的。保持干净,可读性强。以风格或“节省空间”的名义压缩或扭曲它,它变得一团糟。

    所以!鉴于 shell 脚本的总体风格相当巴洛克,任何旨在提高清晰度和易于视觉访问重要符号的东西总是一件好事。

    当您有一个小命令时,将“do”与命令内联写入的形式很甜蜜——我没有发现“do”在视觉上是隐藏的,内部命令也没有真正被掩盖:

    for i in whatever
      do stuff
    done
    

    我觉得这看起来很令人愉快,并且它与 while、if 和 case 类似:

    while condition
      do stuff
    end
    
    if condition
      then stuff1
      else stuff2
    fi
    
    case $blah in
      a) stuff1;;
      b) stuff2;;
      c) stuff3;;
      *) stuffInfinity;;
    esac
    

    清晰和整体整洁是 Codd* 对您的全部要求。

    * Edgar F. Codd,关系数据库理论之父。

    • 4
  5. Zombo
    2018-05-14T14:04:50+08:002018-05-14T14:04:50+08:00

    我很惊讶还没有人提到这种有效且可移植的语法:

    set alfa bravo charlie
    for q do
      echo "$q"
    done
    

    仔细注意for和do在同一行,没有分号。结果:

    alfa
    bravo
    charlie
    
    • 3

相关问题

  • 从文本文件传递变量的奇怪问题

  • 虽然行读取保持转义空间?

  • MySQL Select with function IN () with bash array

  • `tee` 和 `bash` 进程替换顺序

  • 运行一个非常慢的脚本直到它成功

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    如何将 GPG 私钥和公钥导出到文件

    • 4 个回答
  • Marko Smith

    ssh 无法协商:“找不到匹配的密码”,正在拒绝 cbc

    • 4 个回答
  • Marko Smith

    我们如何运行存储在变量中的命令?

    • 5 个回答
  • Marko Smith

    如何配置 systemd-resolved 和 systemd-networkd 以使用本地 DNS 服务器来解析本地域和远程 DNS 服务器来解析远程域?

    • 3 个回答
  • Marko Smith

    如何卸载内核模块“nvidia-drm”?

    • 13 个回答
  • Marko Smith

    dist-upgrade 后 Kali Linux 中的 apt-get update 错误 [重复]

    • 2 个回答
  • Marko Smith

    如何从 systemctl 服务日志中查看最新的 x 行

    • 5 个回答
  • Marko Smith

    Nano - 跳转到文件末尾

    • 8 个回答
  • Marko Smith

    grub 错误:你需要先加载内核

    • 4 个回答
  • Marko Smith

    如何下载软件包而不是使用 apt-get 命令安装它?

    • 7 个回答
  • Martin Hope
    rocky 如何将 GPG 私钥和公钥导出到文件 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add 返回:“连接代理时出错:没有这样的文件或目录” 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll systemctl 状态显示:“状态:降级” 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim 我们如何运行存储在变量中的命令? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S 为什么 /dev/null 是一个文件?为什么它的功能不作为一个简单的程序来实现? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 如何从 systemctl 服务日志中查看最新的 x 行 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - 跳转到文件末尾 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla 为什么真假这么大? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis 在一个巨大的(70GB)、一行、文本文件中替换字符串 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya 为什么 Linux 使用 LF 作为换行符? 2017-12-20 05:48:21 +0800 CST

热门标签

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve