「for」と同じ行に「do」を配置する必要があるのはなぜですか?


28

1.まとめ

わかりません。なぜE010 bashate ruleが必要なのですか。


2.詳細

私はファイルをリントするためにbashateを使用してい.shます。E010ルール:

やると同じライン上にないため

for bashate:

  • 正しい:

    #!/bin/bash
    for f in bash/*.sh; do
        sashacommand "$f"
    done
    
  • エラー:

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

任意の有効な引数は、なぜ私が必要であるfordo同じ行に?


3.役に立たない

私の質問に対する答えが見つかりません:

  1. グーグル
  2. コーディングのベストプラクティスに関する記事(
  3. bashateドキュメンテーション。私が見つけるだけ

    制御ブロックで物事の一貫性を保つのに役立つ一連のルール。これらは、継続のある長い行では無視されます。これは、一種の「興味深い」展開だからです。


3
インデントdoは間違いなく少し珍しいですがfor ... \ndo\n<indent>body...、非常に一般的であり、私はそれよりも多くを推定しますfor ... ; do。それについても文句を言っていますか?
マイケル・ホーマー

20
bashateあるスタイルチェッカーが。スタイルは本質的に主観的です。それが課すアーティファクトスタイルが気に入らない場合は使用しないでください。代わりに、shellcheckのような構文/バグチェッカーを検討する必要があります。
-meuh

@meuh、ありがとう、すでにShellCheckを使用しています。私の質問:E010-だけのスタイルルールまたは私は必要ないくつかのケースでのために行うだけでなく、スタイル上の理由により、同じ行に。
СашаЧерных

10
シェル内の同じ行で実行する必要がある構文上の義務ありません
-meuh

1
@СашаЧерных珍しいのはそれ自体のインデントではなく、のインデントですdo。それは、ifCのような言語の開き中括弧をインデントし、その同じ行にコードを追加するようなものです。別の例では、Pythonで許可されている場合:ifインデントを次の行に入れて同じ行にコードを追加します。ボディに追加の行を追加することで違いを生じさせます。
-JoL

回答:


60

構文的には、次の2つのコードスニペットは正しく、同等です。

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は、「(このforループで)行う必要があることを次に示します」という意味のキーワードです。

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

同じことはthenifステートメントにも当てはまります。

しかし、これも個人のスタイル設定、またはチーム/プロジェクトが使用しているコーディングスタイルに帰着します。


「非常に長いループヘッダーでは、新しい行に入力するのが理にかなっている」と言います。その理由を教えてください。ヘッダーの後にが必要doあるため、次の行にヘッダーを配置すると読みやすくなる理由はわかりません。
コンラッドルドルフ

3
@KonradRudolph私の端末は80文字幅です。リストが折り返される場合、(最後の例のように)連続した行のセットにします。ほとんど折り返される場合、do(またはthen最後の例のように)単独の行に(または)を置きます。これはすべて個人的な好みで解決する必要があります。私の端末は80文字幅しか「ない」ため、また見た目が乱雑だと思うので、私は長すぎる行が好きではありません。また、非常に長い行のエラーを解析することも困難です。
クサラナナンダ

1
これが意見であることを指摘し続ける必要はないようです。bashateはスタイルガイドであるため、本質的に意見に基づいています。
バーマー

4
@Barmar、ここでの質問は「必要」や「ルール」などの言い回しを使用していることに注意してくださいdo。ので、それらは、かなり厳格なフレーズですかなり逆に、いわゆる「ルール」は実際には主観的な意見であることを指摘する価値があるようです。
-ilkkachu

2
@mtraceurそうですね、個人的な好みについては質問していません。ただし、引用する読みやすさの制限はコードには適用されないことに注意してください。散文にのみ適用されます。眼球運動はコードの読み取りでは根本的に異なるため、これらの研究からの証拠はここでは適用できません。そして、理論的根拠としてもはや適用されなくなった歴史的理由を使用することに関しては、過去8.3ファイル名も使用しました。
コンラッドルドルフ

28

ページ上部に表示される内容に注意してください。

bashate:bashスクリプトに相当するpep8

PEP8は、Pythonコードのスタイルガイドです。Pythonの人々は、しばしばスタイルの問題を非常に真剣に受け止めているようです[要出典]、それは単なるガイドです。をdoと同じ行forに配置することと、それを独自の行に配置することの両方の利点を考え出すことができます。

or ブロック(など)を{開始するときにCコードをどこに配置するかと同じ議論です。ifwhile


ドキュメントの数行下には、もう1つの興味深いルールがあります。

E020:関数宣言が形式ではありません ^function name {$

ここでのポイントは、スタイルガイドの作成者がfunction、読者が関数宣言を認識するためにキーワードを使用する必要があると考えていることだと思います。ただし、これfunction fooは関数を定義する標準的な方法ですfoo()。標準的な方法はです。2つの(Bashの)唯一の違いは、/bin/shDebianやUbuntuのように、もう一方が標準シェルに移植するのが難しいことです。

だから、私はそのようなスタイルガイドを一粒か三粒で取り、最良のスタイルが何であるかを自分で決めることを提案するだろう。優れたスタイルチェッカーを使用すると、一部のチェックを無効にすることができます(bashateではbashate -i E010,E011これら2つのチェックを無視する必要があります)。


12

TL; DR:する必要はありません。それは単なる男の意見です。

他の多くの人と同様に、私はfor何十年もこのようなループを書いてきました。

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

このレイアウトは、do ... doneCのような言語の波括弧のようにループ本体を囲む事実を強調し、ループ構造のコンポーネントを改行で区切ることができます。

もちろん、中括弧を配置する場所についても宗教戦争がありますので、ju審員はまだこの中にいると言えます。私見、これは明らかにこれが動作するように設計された方法です。ボーンは一致する区切り文字が好きでした、cf。if ... ficase ... esacおよび、短いバージョンでセミコロンが必要なことは、元の設計よりも短くしていることを示しています。それに関して何も悪いことはありません。テクノロジーが進歩し、かつては良いアイデアのように思われた多くのことが、今では嫌われていますgoto。しかし、シェルスクリプトコミュニティ全体がbashate著者の好みを採用するまで、何もする必要はありません。


3
fi対応していることif、およびesacなどがアルゴル68だけの理由から来ているforループは「S doで終了されていないodことがあるod既存の標準ユーティリティの名前です。en.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix
Kusalanandaを

1
右、およびキーワードで区切られたブロックは、Pascal(begin ... endなどを使用)など、Algolファミリーの他の言語でも使用されていました。
アレクシス

2
についての話を聞いていませんでしたod、それは面白いです...(なぜ、forループをrofで終わらせないのですか?)
アレクシス

2
@alexisまあ、Kusalanandaが言ったように、それはAlgol 68から来ています。それが重要なポイントです。オリジナルのBourneシェルの作成者であるStephen Bourneは、その言語の影響を強く受けていたため、その構文にこだわったのです。彼がCで書いていたときでさえ、bourneシェルのソースコードを参照してください:minnie.tuhs.org//cgi-bin/utree.pl?file=V7 / usr / src / cmd / sh / mac.h ああ、そして方法、BEGINおよびENDそこにも定義されています。
セルギーKolodyazhnyy

1
ちなみに、この全体の書式設定スタイルは、Algol 68にも由来しています。ループ全体が簡単に1行に収まる場合を除き、慣例により、そのFORand DOも別々の行になります。
reinierpost

3

誰もこの有効で移植性のある構文に言及していないことに驚いています。

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

fordoがセミコロンなしで同じ行にあることに注意してください。結果:

alfa
bravo
charlie

このあいまいな(ただし、クリーンでポータブルなシェルコードにとっては重要な)構文の言及を差し込むことに対するこの回答を承認しますが、これが位置パラメーターを壊すことを人々に明示的に説明する価値があり、また、唯一の「真のポータブル(tm)」フォームは、for qdoが別々の行にあるフォームです(この例のフォームは、数十年前、元のAlmquishシェル(ash)でサポートされていませんでしたin-ulm.de/~mascheck/various/ bourne_args /#endnote
mtraceur

この回答の例は私には有効ですが、OPの質問の例にそれを適用しても機能しませ
Scribblemacher

3

ここでいくつかの良い答え。スタイルガイドは常に一粒の塩味で、私見と経験を積んで、スタイルに関して過度のドグマに満ちているコミュニティについては、これまでよりもやや中程度の懸念を抱いてください。彼らが最後に私が点在し、最後のTが交差したときに最終的にソフトウェアが動作すると信じているようです。時々、バグを削除するには完璧なスタイル以上のものが必要です...

シェルの学習を開始したとき、ほとんどのスクリプトとチュートはインラインセミコロン形式を使用していました

for i in "$@"; do
    stuff
done

しかし、私は経験が浅かったので、私はそれを見つけるのに少し苦労しました。およびdo-両方が構文の正確さを確認するために不可欠です。そのため、次の行のdoを単独で使用することを好みました。私はもうそれをしません(意図されたしゃれ)

さらに、「while」コマンドは、素敵な小さなトリックの優れた候補です。

while prep1; prep2; condition; do
    stuff
done

ただし、prepコマンドが少しかさばる、および/または条件が複雑な場合は、

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

すべてのステートメントは式であるためです。両方のスタイルが日和見的に使用されていることに注目してください。それをきれいに保ち、それは非常に読みやすいです。スタイルまたは「スペースを節約する」という名前でそれを圧縮またはゆがめ、それは恐ろしい混乱になります。

そう!一般にシェルスクリプトのややバロック様式のスタイルを考えると、重要なシンボルへの明快さと視覚的なアクセスを向上させることを目的とするものは常に良いことです。

「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、リレーショナルデータベース理論の父。


1
前に条件で見たことwhileがないif。クール!
ジョー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.