ทำไมฉันต้องวาง "ทำ" ในบรรทัดเดียวกันกับ "สำหรับ"


28

1. สรุป

ผมไม่เข้าใจว่าทำไมฉันต้องกฎ bashate E010


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
    

เหตุผลใดที่ฉันต้องการforและdoอยู่ในบรรทัดเดียวกัน


3. ไม่มีประโยชน์

ฉันไม่พบคำตอบสำหรับคำถามของฉันใน:

  1. Google
  2. บทความเกี่ยวกับแนวทางปฏิบัติในการเข้ารหัสที่ดีที่สุด ( ตัวอย่าง )
  3. เอกสาร bashate ฉันพบเพียง :

    ชุดของกฎที่ช่วยให้สิ่งต่าง ๆ สอดคล้องกันในบล็อกควบคุม สิ่งเหล่านี้จะถูกมองข้ามบนเส้นยาวที่มีความต่อเนื่องเพราะการคลายตัวซึ่งเป็น“ น่าสนใจ”


3
รอยเว้าdoนั้นผิดปกติเล็กน้อย แต่for ... \ndo\n<indent>body...เป็นเรื่องธรรมดามากและฉันก็ประมาณได้มากกว่าfor ... ; doนั้น มันบ่นเกี่ยวกับเรื่องนั้นด้วยหรือไม่?
Michael Homer

20
bashateเป็นตัวตรวจสอบสไตล์ รูปแบบเป็นอัตนัยโดยเนื้อแท้ อย่าใช้มันหากคุณไม่ชอบสไตล์ของไลบรารี คุณควรพิจารณาตัวตรวจสอบไวยากรณ์ / ข้อผิดพลาดเช่นshellcheckแทน
meuh

@ meuh ขอบคุณฉันใช้ ShellCheck แล้ว คำถามของฉัน: E010- เพียงรูปแบบการปกครองหรือในบางกรณีที่ฉันต้องการสำหรับและทำในบรรทัดเดียวกันโดยไม่เพียง แต่เหตุผลสไตล์
СашаЧерных

10
ไม่ต้องมีภาระผูกพันที่จะมีประโยคสำหรับและทำในบรรทัดเดียวกันในเปลือก
meuh

1
@ doСашаЧерныхมันไม่เยื้องด้วยตัวเองที่ผิดปกติก็เยื้องของ มันเหมือนกับการเยื้องการเปิดวงเล็บปีกกาของifและเพิ่มรหัสในบรรทัดเดียวกันในภาษาเช่น C ตัวอย่างอื่น ๆ ถ้าหลามอนุญาตให้มันจะวาง:ของifเยื้องในบรรทัดถัดไปและเพิ่มรหัสในบรรทัดเดียวกันนั้น มันจะทำให้มันแตกต่างกับสายเพิ่มเติมในร่างกาย
JoL

คำตอบ:


60

ตัวอย่างโค้ดสองรายการต่อไปนี้ถูกต้องและเทียบเท่า:

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

คนหลังอาจบอกว่าเป็นการยากที่จะอ่านdoเล็กน้อย obfuscates คำสั่งในร่างกายของวง หากการวนซ้ำมีหลายคำสั่งและคำสั่งถัดไปอยู่ในบรรทัดใหม่การ obfuscation จะถูกเน้นเพิ่มเติม:

for f in *
    do cmd1
    cmd2
done

... แต่การติดธงว่าเป็น "ข้อผิดพลาด" คือความเห็นส่วนตัวของใครบางคน IMHO มากกว่าความจริงวัตถุประสงค์

โดยทั่วไปแล้วเกือบทั้งหมด;อาจถูกแทนที่ด้วยการขึ้นบรรทัดใหม่ ทั้งสอง;และขึ้นบรรทัดใหม่เป็นตัวยกเลิกคำสั่ง 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

เดียวกันจะไปสำหรับthenในifคำสั่ง

แต่อีกครั้งสิ่งนี้เกิดขึ้นกับการตั้งค่าสไตล์ส่วนตัวของตัวเองหรือกับการเขียนโปรแกรมหรือโปรเจ็กต์ที่ทีมของคุณใช้


คุณพูดว่า“ ในส่วนหัววนที่ยาวมากมันอาจสมเหตุสมผลที่จะนำไปทำในบรรทัดใหม่” คุณสามารถให้เหตุผลได้หรือไม่? เนื่องจากส่วนหัวต้องตามมาdoฉันไม่เห็นเหตุผลที่วางไว้ในบรรทัดถัดไปจะช่วยให้สามารถอ่านได้
Konrad Rudolph

3
@KonradRudolph เทอร์มินัลของฉันมีความกว้าง 80 อักขระ หากรายการนั้นฉันจะทำให้มันเป็นชุดของเส้นต่อเนื่อง (เช่นในตัวอย่างสุดท้ายของฉัน) ถ้ามันเกือบจะปิดฉันจะใส่do(หรือthen) ในบรรทัดด้วยตัวเอง (เช่นในตัวอย่างที่สองถึงล่าสุด) ทั้งหมดนี้เกี่ยวข้องกับความชอบส่วนบุคคล ฉันไม่ชอบเส้นที่ยาวเกินไปส่วนหนึ่งเป็นเพราะเทอร์มินัลของฉันมี "กว้าง" เพียง 80 ตัวอักษรและอีกส่วนหนึ่งเพราะฉันคิดว่ามันดูไม่เรียบร้อย ฉันพบว่ามันยากที่จะแยกวิเคราะห์บรรทัดที่ยาวมากสำหรับข้อผิดพลาด
Kusalananda

1
ดูเหมือนไม่จำเป็นเลยที่จะชี้ให้เห็นว่านี่เป็นความคิดเห็น bashate เป็นไกด์สไตล์ดังนั้นจึงขึ้นอยู่กับความคิดเห็น
Barmar

4
@Barmar โปรดทราบว่าคำถามที่นี่ใช้การใช้ถ้อยคำเช่น "need to" และ "rule" และ readme ของ bashate จะมีdoคำว่า "error" ในบรรทัดแยกต่างหาก เหล่านี้คือวลีที่ค่อนข้างเข้มงวดจึงไม่ดูเหมือนคุ้มค่าที่จะชี้ให้เห็นว่าค่อนข้างในทางตรงกันข้ามการที่เรียกว่า "กฎ" เป็นจริงเป็นเพียงแค่ความคิดเห็นอัตนัย
ilkkachu

2
@mtraceur ใช่ฉันไม่ได้ตั้งคำถามเกี่ยวกับความชอบส่วนตัว แต่โปรดทราบว่าการ จำกัด การอ่านคอลัมน์ที่คุณอ้างไม่สามารถใช้กับรหัสได้ ใช้กับร้อยแก้วเท่านั้น การเคลื่อนไหวของดวงตานั้นมีความแตกต่างกันอย่างมากสำหรับการอ่านโค้ดดังนั้นหลักฐานจากการศึกษาเหล่านี้จึงไม่สามารถใช้ได้ที่นี่ และสำหรับการใช้เหตุผลทางประวัติศาสตร์ที่ไม่ได้ใช้เป็นเหตุผลเราก็ใช้ชื่อไฟล์ 8.3 ที่ผ่านมา
Konrad Rudolph

28

สังเกตสิ่งที่มันบอกไว้ที่ด้านบนของหน้า:

bashate: pep8 ที่เทียบเท่าสำหรับสคริปต์ทุบตี

PEP8เป็นคู่มือสไตล์สำหรับรหัสหลาม ในขณะที่คนหลามมักจะดูเหมือนจะนำประเด็นสไตล์ของพวกเขาเป็นอย่างมาก[อ้างจำเป็น]มันเป็นเพียงที่แนะนำ เราสามารถสร้างอัพไซด์ขึ้นมาเพื่อวางทั้งคู่doในบรรทัดเดียวกันกับforและวางมันลงบนเส้นของมันเอง

มันเป็นการสนทนาแบบเดียวกับที่ใส่{ในรหัส C เมื่อเริ่มต้นifหรือwhileบล็อก (หรือเช่นนั้น)


บรรทัดด้านล่างในเอกสารประกอบมีกฎที่น่าสนใจอีกข้อหนึ่ง:

E020: การประกาศฟังก์ชันไม่อยู่ในรูปแบบ ^function name {$

ฉันถือว่าจุดที่นี่คือผู้เขียนคู่มือสไตล์คิดว่าการใช้functionคำหลักเป็นสิ่งจำเป็นสำหรับผู้อ่านที่จะรับรู้การประกาศฟังก์ชั่น อย่างไรก็ตามfunction fooเป็นที่ไม่ได้มาตรฐานวิธีการกำหนดฟังก์ชั่น: foo()วิธีมาตรฐานคือ ข้อแตกต่างระหว่างสอง (ใน Bash) คือความแตกต่างระหว่างพอร์ตกับเชลล์มาตรฐานเช่น/bin/shDebian หรือ Ubuntu นั้นยากกว่า

ดังนั้นฉันขอแนะนำให้นำไกด์สไตล์ใด ๆ และทุกอย่างมาด้วยเกลือเม็ดหนึ่งหรือสามเม็ดและตัดสินใจด้วยตัวคุณเองว่าสไตล์ที่ดีที่สุดคืออะไร ตัวตรวจสอบรูปแบบที่ดีช่วยให้ปิดการใช้งานการตรวจสอบบางอย่าง (bashate bashate -i E010,E011จะต้องเพิกเฉยต่อการตรวจสอบสองอย่างนี้) ตัวตรวจสอบรูปแบบที่ยอดเยี่ยมจะช่วยให้คุณสามารถแก้ไขการทดสอบได้เช่นการตรวจสอบ E020 ตรงข้าม


12

TL; DR: คุณไม่จำเป็นต้องทำ มันเป็นเพียงความเห็นของเพื่อนบางคน

เช่นเดียวกับคนอื่น ๆ ฉันเขียนforลูปแบบนี้มานานหลายทศวรรษ

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

เลย์เอาต์นี้เน้นถึงความจริงที่do ... doneล้อมรอบลำตัววนเช่นปีกกาในภาษา C และอนุญาตให้ขึ้นบรรทัดใหม่เพื่อแยกส่วนประกอบของโครงสร้างวนรอบ

แน่นอนว่ามีสงครามทางศาสนาเกี่ยวกับตำแหน่งที่จะจัดฟันด้วยเช่นกันดังนั้นคุณอาจบอกว่าคณะลูกขุนยังคงออกมา IMHO นี่เป็นสิ่งที่ชัดเจนว่าสิ่งนี้ถูกออกแบบมาเพื่อทำงานอย่างไร Bourne ชื่นชอบตัวคั่นที่ตรงกัน cf if ... fi, case ... esacและความจำเป็นในการอัฒภาคในรุ่นสั้นเผยให้เห็นว่าคุณกำลังทำให้มันสั้นกว่าการออกแบบเดิม ไม่มีอะไรผิดปกติกับที่; gotoความก้าวหน้าด้านเทคโนโลยีและจำนวนมากของสิ่งที่ครั้งหนึ่งเคยดูเหมือนจะเป็นความคิดที่ดีจะขมวดคิ้วตอนนี้เมื่อเป็นเช่น แต่จนกว่าชุมชนการเขียนสคริปต์เชลล์ทั้งหมดจะใช้การตั้งค่าของbashateผู้เขียนคุณไม่ต้องทำอะไรเลย


3
สิ่งfiที่สอดคล้องกับifและesacอื่น ๆ มาจาก Algol 68 เหตุผลเดียวที่forลูปdoไม่ได้จบลงodก็odคือชื่อของยูทิลิตี้มาตรฐานที่มีอยู่ ดูen.wikipedia.org/wiki/ALGOL_68C#Algol_68C_and_Unix
Kusalananda

1
ถูกต้องและบล็อกที่คั่นด้วยคำหลักยังใช้ในภาษาอื่น ๆ ของตระกูล Algol รวมถึง Pascal (ซึ่งใช้begin ... endฯลฯ )
alexis

2
ไม่เคยได้ยินเรื่องเกี่ยวกับodว่าเป็นตลก ... ( แต่ทำไมไม่เพียงจบสำหรับลูปด้วยrofแล้ว?)
อเล็กซิส

2
@alexis ดีเช่น Kusalananda กล่าวว่ามันมาจาก Algol 68 นั่นคือจุดสำคัญ สตีเฟ่นบอร์นผู้สร้างเชลล์บอร์นต้นฉบับได้รับอิทธิพลอย่างมากจากภาษานั้นและนั่นเป็นสาเหตุที่เขาติดอยู่กับไวยากรณ์นั้น แม้ตอนที่เขาเขียนใน C. ดูซอร์สโค้ดสำหรับเชลล์บอร์น: minnie.tuhs.org//cgi-bin/utree.pl?file=V7/usr/src/cmd/sh/mac.h โอ้และโดย วิธีการBEGINและENDมีการกำหนดไว้เช่นกัน
Sergiy Kolodyazhnyy

1
สไตล์การจัดรูปแบบทั้งหมดนี้มาจาก Algol 68 มันFORและDOก็จะอยู่ในบรรทัดที่แยกจากกันโดยการประชุมยกเว้นเมื่อทั้งวงจะง่ายในบรรทัดเดียว
reinierpost

3

ฉันประหลาดใจที่ไม่มีใครพูดถึงไวยากรณ์ที่ถูกต้องและพกพาได้:

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

สังเกตอย่างระมัดระวังว่าforและdoอยู่ในบรรทัดเดียวกันโดยไม่มีเครื่องหมายอัฒภาค ผล:

alfa
bravo
charlie

ฉันเห็นด้วยกับคำตอบนี้สำหรับการเสียบการกล่าวถึงสิ่งที่คลุมเครือ (แต่สำคัญสำหรับการเชลล์โค้ดแบบพกพาที่สะอาดและพกพาในบางกรณี) แต่มันก็คุ้มค่าที่จะอธิบายให้คนฟังอย่างชัดเจนว่าสิ่งนี้ทำให้พารามิเตอร์ตำแหน่งผิดเพี้ยน เฉพาะ "แบบพกพาอย่างแท้จริง (tm)" รูปแบบเป็นที่ที่for qและdoอยู่ในบรรทัดที่แยกต่างหาก (รูปแบบในตัวอย่างนี้ไม่ได้รับการสนับสนุนสองสามทศวรรษที่ผ่านมาในเปลือก Almquish เดิม ( ash): in-ulm.de/~mascheck/various/ bourne_args / # endnote )
mtraceur

ในขณะที่ตัวอย่างในคำตอบนี้ใช้งานได้สำหรับฉันการใช้กับตัวอย่างในคำถามของ OP ไม่ทำงาน
Scribblemacher

3

คำตอบที่ดีหลายอย่างที่นี่ มักจะนำไกด์สไตล์ที่มีเม็ดเกลือและ IMHO และประสบการณ์มาให้ความห่วงใยในชุมชนที่มีความเชื่อมั่นมากเกินไปเล็กน้อยพอสมควร มันเกือบจะเหมือนที่พวกเขาเชื่อว่าเมื่อพวกเขาได้ในที่สุดฉันก็จุดและสุดท้าย T ข้ามแล้วซอฟต์แวร์จะทำงาน บางครั้งมันใช้เวลามากกว่าสไตล์ที่สมบูรณ์แบบในการลบข้อบกพร่อง ...

เมื่อฉันเริ่มเรียนรู้เชลล์, สคริปต์และ tutes ส่วนใหญ่ใช้รูปแบบอัฒภาคในบรรทัด

for i in "$@"; do
    stuff
done

แต่เนื่องจากฉันไม่มีประสบการณ์ฉันมีช่วงเวลาที่ยากลำบากในการตรวจหา และ - ทั้งสองสิ่งจำเป็นสำหรับการยืนยันความถูกต้องของประโยค ดังนั้นฉันจึงชอบทำในบรรทัดถัดไปทั้งหมดด้วยตัวเอง ฉันไม่ทำเช่นนั้นอีกแล้ว (เล่นสำนวนเจตนา)

นอกจากนี้คำสั่ง 'while' เป็นตัวเลือกที่ยอดเยี่ยมสำหรับเคล็ดลับเล็กน้อย:

while prep1; prep2; condition; do
    stuff
done

แต่เมื่อคำสั่งเตรียมการมีขนาดค่อนข้างใหญ่และ / หรือเงื่อนไขนั้นซับซ้อน

while
    prep1
    prep2
    condition
do
    stuff
done

และต่อท้ายสิ่งที่ต้องทำในฐานะ "; ทำ" เป็นสิ่งที่ไม่ดีในทางบวก

คุณสามารถเพิ่มความเข้มข้นได้มากกว่านั้น:

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

เพราะทุกคำสั่งเป็นการแสดงออก สังเกตว่ามีการใช้รูปแบบทั้งสองอย่างฉวยโอกาสอย่างไร รักษาความสะอาดและสามารถอ่านได้ค่อนข้าง กระชับหรือบิดมันในชื่อของสไตล์หรือ "การประหยัดพื้นที่" และกลายเป็นความยุ่งเหยิงที่น่ากลัว

ดังนั้น! เมื่อพิจารณาจากสไตล์สคริปต์บาร็อคโดยทั่วไปแล้วอะไรก็ตามที่มีจุดประสงค์เพื่อเพิ่มความชัดเจนและการเข้าถึงสัญลักษณ์ที่สำคัญได้ง่ายนั้นเป็นสิ่งที่ดีเสมอ

รูปแบบที่ 'ทำ' ถูกเขียนขึ้นด้วยคำสั่งจะหวานเมื่อคุณมีคำสั่งเล็ก ๆ น้อย ๆ - ฉันไม่พบ 'ทำ' ที่ซ่อนอยู่ทางสายตาและไม่ได้เป็นคำสั่งภายในที่บดบังจริง ๆ :

for i in whatever
  do stuff
done

ฉันพบว่าค่อนข้างน่าพอใจที่จะดูและมันมี analogues กับในขณะที่ถ้าและกรณี:

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เงื่อนไขมาก่อน เย็น!
Joe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.