ลำไส้ใหญ่ภายในมีจุดประสงค์อะไร


44

ฉันแฮ็คสคริปต์เชลล์จำนวนมากและบางครั้งสิ่งที่ง่ายที่สุดก็ทำให้ฉันยุ่งเหยิง วันนี้ฉันพบสคริปต์ที่ใช้:ทุบตี (โคลอน) builtin อย่างกว้างขวาง

Documenationดูเหมือนว่าพอง่าย:

: (a colon)  
     : [arguments]  

อย่าทำอะไรเลยนอกเหนือจากการขยายข้อโต้แย้งและทำการเปลี่ยนเส้นทาง สถานะการส่งคืนเป็นศูนย์

อย่างไรก็ตามก่อนหน้านี้ฉันเคยเห็นสิ่งนี้ใช้ในการสาธิตการขยายตัวของเชลล์ กรณีการใช้งานในสคริปต์ที่ฉันวิ่งข้ามได้ใช้โครงสร้างนี้อย่างกว้างขวาง:

if [ -f ${file} ]; then
    grep some_string ${file} >> otherfile || :
    grep other_string ${file} >> otherfile || :
fi

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

ฉันกำลังอ่านสิ่งนี้เป็นสิ่งก่อสร้างที่ไร้ประโยชน์ที่ระบุว่า "หรือไม่ทำอะไรเลย" มีจุดประสงค์อะไรที่จะจบ greps เหล่านี้ด้วย "หรือไม่ทำอะไร" รับใช้? โครงสร้างนี้จะทำให้เกิดผลลัพธ์ที่แตกต่างไป|| :จากในทุกกรณีหรือไม่?


10
วัตถุประสงค์หนึ่งที่เป็นไปได้ผมสามารถมองเห็นคือการใช้เป็นทางเลือก: trueอาจerrexitมีการตั้งค่าไว้และผู้เขียนไม่สนใจสถานะการออกของบางคำสั่ง
jw013


หน้าการเชื่อมโยง Stackoverflow เป็น IMO ที่ครอบคลุมมากขึ้นเล็กน้อย (ดีมากที่จะอ่านทั้งหน้านี้และหน้าที่เชื่อมโยง)
เทรเวอร์บอยด์สมิ ธ

คำตอบ:


29

มันปรากฏในสคริปต์ของคุณจะถูกใช้แทน: trueหากgrepไม่พบคู่ที่ตรงกันในไฟล์มันจะส่งคืนรหัสทางออกที่ไม่ใช่ศูนย์ ตามที่ jw013 ระบุไว้ในความคิดเห็นหากerrexitมีการตั้งค่าไว้อาจจะ-eอยู่ในบรรทัด Shebang สคริปต์จะออกจากหากผู้ใดgrepไม่พบการแข่งขัน เห็นได้ชัดว่านั่นไม่ใช่สิ่งที่ผู้เขียนต้องการดังนั้น (s) เขาเพิ่ม|| :เพื่อให้ออกจากสถานะของคำสั่งสารประกอบที่โดยเฉพาะอย่างยิ่งศูนย์เสมอเหมือนกันมากขึ้น (ในประสบการณ์ของฉัน) /|| true|| /bin/true


ดุจ นี่เป็นแนวคิดของสคริปต์สร้าง RPM และในขณะที่ฉันไม่เห็นการตรวจสอบรหัสออกจากภายในสคริปต์ฉันลืมที่จะพิจารณาว่ากระบวนการหลักอาจดูอยู่
Caleb

8
หากเป็นกรณีนี้ฉันจะเรียกมันว่าการฝึกเขียนบทที่ไม่ดี มันใช้งานได้เทียบเท่ากับการใช้งานtrueแทน แต่ความหมายเชิงความหมายนั้นชัดเจนกว่าtrueมาก :เหมาะสมกว่าเมื่อต้องการ NOP อย่างชัดเจน
jw013

จากประสบการณ์ของฉันนี่เป็นวิธีปฏิบัติทั่วไปในสคริปต์ RPM มันอาจจะไม่ควร แต่เราอยู่ที่นั่น
mattdm

นักพิถีพิถันบางคนชอบ:แทนที่จะเป็นtrueเพราะในตัวที่มักจะเป็นไบนารีที่รวบรวมด้วยค่าใช้จ่ายเพิ่มเติม ฉันมักจะใช้เพราะรหัสสามารถอ่านได้มากขึ้น (เช่นฉันต้องการใช้แทน) :bashtruetruesource.
เทรเวอร์บอยด์สมิ ธ

36

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

# assign FOO=bar iff FOO is unset
: ${FOO:=bar}

2
มาที่นี่เพื่อค้นหาสิ่งนี้ทำให้งงงันเมื่อฉันเห็นรูปแบบนี้ในสคริปต์เพื่อประกาศค่าเริ่มต้น
ffledgling

20

ฉันนึกถึงสถานที่สองแห่งที่ฉันเคยใช้:ในอดีต

while :
do
     shell commands
     some exit condition
done

นั่นคือการวนซ้ำตลอดไป

function doSomethingStub {
    :
}

ใส่ฟังก์ชั่น stub เพื่อให้การควบคุมการไหลของระดับบนถูกต้อง

ใช้ครั้งเดียวที่ฉันเคยเห็นในสมัยก่อน: แทนที่จะเป็น#!/bin/shบรรทัด (หรืออะไรก็ตาม) คุณจะเห็น:บรรทัด เมล็ด Real Unix ที่แก่กว่าหรือเชลล์ Real Unix รุ่นเก่าจะใช้สิ่งนั้นเพื่อหมายถึง ในขณะที่ฉันจำได้ว่านี่เป็นเพียงเมื่อ csh ทำให้ inroads เป็นเปลือกโต้ตอบทั่วไป


@BruceEdiger: คุณมีการอ้างอิงถึงบรรทัด "shecolon" หรือไม่?
l0b0

7
ในที่สุดก็พบการอ้างอิง ": ที่จุดเริ่มต้นของสคริปต์" และคำอธิบาย: faqs.org/faqs/unix-faq/faq/part3/section-16.html
Bruce Ediger

1
พฤติกรรมในตอนเริ่มต้น:นั้นแปลกมาก ฉันพบว่ามันทำให้สคริปต์ทำงานด้วยshจริง ๆ เมื่อคุณเริ่มต้นสคริปต์โดยไม่มี shebang ... มันจะพยายามเรียกใช้สคริปต์กับเชลล์ที่กำลังทำงานอยู่ (ดังนั้นถ้าคุณกำลังเรียกใช้สคริปต์จะพยายามเรียกใช้สคริปต์bashราวกับbashว่าคุณมีcshแล้วพยายามเรียกใช้เป็นcsh)
เทรเวอร์บอยด์สมิ ธ

18

:ในตัวอยู่แล้วในธ อมป์สันเปลือก - มันเอกสารสำหรับUnix V6ในปี 1975 ใน ธ อมป์สันเปลือก:ระบุฉลากสำหรับgotoคำสั่ง หากคุณไม่เคยพยายามโทรหาgotoสายที่ขึ้นต้นด้วยแสดงว่าบรรทัดนั้นเป็นความเห็นที่มีประสิทธิภาพ

บอร์นเชลล์ , หอยบรรพบุรุษของบอร์น / POSIX ที่เรารู้ว่าพวกเขาไม่เคยมีgotoที่ฉันรู้ แต่ก็ยังคง:เป็นคำสั่งที่ไม่มี-op (มันมีอยู่แล้วในปัจจุบันระบบปฏิบัติการยูนิกซ์ V7 )


11

ฉันขุดการอ้างอิงเก่า: "สภาพแวดล้อมการเขียนโปรแกรม UNIX" (c) 1984 โดย Kernighan และ Pike

หน้า 147 (การเขียนโปรแกรมเชลล์) บอกสิ่งนี้:

":" เป็นคำสั่งในตัวของเชลล์ที่ไม่ทำอะไรนอกจากประเมินค่าอาร์กิวเมนต์และส่งคืน "true" แทนที่จะ [อ้างอิงจากตัวอย่างสคริปต์] เราสามารถใช้จริงได้ซึ่งเพียงแค่คืนสถานะการออกจริง (นอกจากนี้ยังมีเท็จคำสั่ง.) แต่ ':' มีประสิทธิภาพมากขึ้นกว่าที่เป็นจริงเพราะมันไม่ได้รันคำสั่งจากระบบแฟ้ม [ตัวเอียง / เน้นเป็นของฉัน]


2
แน่นอนว่าtrueตอนนี้เป็น shell builtin แล้วในหลาย ๆ ระบบ
tripleee

8

ฉันดูเหมือนจะจำได้ว่ารุ่นก่อนหน้าของเชลล์ไม่มีไวยากรณ์ความคิดเห็น บรรทัดที่ขึ้นต้นด้วย:(ซึ่งอาจเป็นปฏิบัติการจริงคล้ายกับ/bin/true) จะเป็นทางเลือกที่ดีที่สุด

นี่คือหน้าคนสำหรับเปลือก Thompsonโบราณ(ไม่มีส่วนเกี่ยวข้อง); ไม่มีการกล่าวถึงไวยากรณ์ของความคิดเห็นใด ๆ


4
ต้นกำเนิดของ:ในความเป็นจริงตัวบ่งชี้ที่ป้ายสำหรับgotoคำสั่งในเปลือกโบราณบางคน (ผมไม่ทราบว่าที่) ฉลากแน่นอนสามารถนำมาใช้เป็นความคิดเห็นถ้าไม่มีการจับคู่: something gotoการปฏิบัติที่ติดอยู่แม้จะgotoหายไป
Gilles 'หยุดความชั่วร้าย'

8

":" เหมาะสำหรับการแก้ไขข้อบกพร่อง

DEBUGLOG=": debugfunction"

statement
statement
$DEBUGLOG arg1 arg2 ...
statement
statement

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

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

: << COMMENT
all --statements --in --here
are now -a here document which are
passed to --the noop
COMMENT
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.