มีคำสั่ง "goto" ในทุบตี?


204

มีคำสั่ง "goto" ในการทุบตี? ฉันรู้ว่ามันเป็นการปฏิบัติที่ไม่ดี แต่ฉันต้องการ "ข้าม" โดยเฉพาะ


4
ไม่ไม่มีการgotoทุบตี (อย่างน้อยก็บอกcommand not foundสำหรับฉัน) ทำไม? โอกาสที่จะมีวิธีที่ดีกว่าที่จะทำ
Niklas B.

153
เขาอาจมีเหตุผลของเขา ฉันพบคำถามนี้เพราะฉันต้องการให้มีgotoคำสั่งข้ามรหัสจำนวนมากสำหรับการดีบักสคริปต์ขนาดใหญ่โดยไม่ต้องรอชั่วโมงเพื่อให้งานที่ไม่เกี่ยวข้องต่าง ๆ เสร็จสมบูรณ์ แน่นอนว่าฉันไม่ได้ใช้gotoรหัสในการผลิต แต่สำหรับการดีบั๊กรหัสของฉันมันจะทำให้ชีวิตของฉันง่ายขึ้นอย่างไม่สิ้นสุด
Karl Nicoll

30
@delnan แต่ไม่มี goto สามารถทำให้บางสิ่งที่ซับซ้อนมากขึ้น มีกรณีการใช้งานอย่างแน่นอน
glglgl

71
ฉันเบื่อกับตำนาน goto! ไม่มีอะไรผิดปกติกับ goto! ทุกสิ่งที่คุณเขียนในที่สุดก็จะกลายเป็น ในแอสเซมเบลอร์มีเพียง goto เหตุผลที่ดีในการใช้ goto ในภาษาการเขียนโปรแกรมที่สูงขึ้นเป็นตัวอย่างการกระโดดออกจากลูปซ้อนในวิธีที่สะอาดและอ่านได้
Alexander Czutro

25
"หลีกเลี่ยง goto" เป็นกฎที่ดี เช่นเดียวกับกฎใด ๆ มันควรจะเรียนรู้ในสามขั้นตอน ครั้งแรก: ปฏิบัติตามกฎจนกระทั่งเป็นลักษณะที่สอง ประการที่สองเรียนรู้ที่จะเข้าใจเหตุผลของกฎ ประการที่สามเรียนรู้ข้อยกเว้นที่ดีของกฎโดยอาศัยความเข้าใจที่ครอบคลุมว่าจะปฏิบัติตามกฎและเหตุผลของกฎได้อย่างไร หลีกเลี่ยงการข้ามขั้นตอนข้างต้นซึ่งจะเหมือนกับการใช้ "goto" ;-)
Jeff Learman

คำตอบ:


75

ไม่ไม่มี ดู§3.2.4 "Compound คำสั่ง" ในทุบตีคู่มืออ้างอิงสำหรับข้อมูลเกี่ยวกับโครงสร้างการควบคุมที่ทำมีอยู่ โดยเฉพาะให้สังเกตการกล่าวถึงbreakและcontinueซึ่งไม่ยืดหยุ่นเท่าgotoแต่มีความยืดหยุ่นใน Bash มากกว่าในบางภาษาและอาจช่วยให้คุณบรรลุสิ่งที่คุณต้องการ (ไม่ว่าคุณจะต้องการอะไรก็ตาม ... )


10
คุณสามารถขยาย "ความยืดหยุ่นใน Bash มากกว่าในบางภาษา" ได้หรือไม่?
user239558

21
@ user239558: บางภาษาอนุญาตให้คุณไปbreakหรือcontinueกลับจากลูปด้านในสุดเท่านั้นในขณะที่ Bash ให้คุณระบุจำนวนของลูปในการกระโดด (และแม้กระทั่งภาษาที่อนุญาตให้คุณbreakหรือcontinueจากลูปโดยพลการส่วนใหญ่ต้องการให้แสดงแบบคงที่ - เช่นbreak foo;จะแตกออกจากวงวนที่มีป้ายกำกับfoo- ในขณะที่ใน Bash มันแสดงแบบไดนามิก - เช่นbreak "$foo"จะแตกออกจาก$fooลูป )
ruakh

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

@ruakh จริงหลายภาษาช่วยให้มากกว่าน่าขยะแขยงของทุบตีbreak LABEL_NAME; break INTEGER;
Sapphire_Brick

1
@Sapphire_Brick: ใช่ฉันพูดถึงในความคิดเห็นที่คุณตอบกลับ
ruakh

124

หากคุณใช้มันเพื่อข้ามส่วนหนึ่งของสคริปต์ขนาดใหญ่สำหรับการดีบั๊ก (ดูความคิดเห็นของ Karl Nicoll) ถ้าเป็นเท็จอาจเป็นตัวเลือกที่ดี (ไม่แน่ใจว่า "false" พร้อมเสมอสำหรับฉันมันอยู่ใน / bin / false) :

# ... Code I want to run here ...

if false; then

# ... Code I want to skip here ...

fi

# ... I want to resume here ...

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


6
ใช่falseพร้อมใช้งานเสมอ แต่ถ้าคุณมีบล็อกของรหัสที่คุณไม่ต้องการดำเนินการเพียงแค่แสดงความคิดเห็นออก หรือลบมัน (และดูในระบบควบคุมแหล่งที่มาของคุณหากคุณต้องการกู้คืนในภายหลัง)
Keith Thompson

1
หากกลุ่มของรหัสยาวเกินไปที่จะแสดงความคิดเห็นออกทีละบรรทัดอย่างน่าเบื่อโปรดดูเทคนิคเหล่านี้ stackoverflow.com/questions/947897/… อย่างไรก็ตามสิ่งเหล่านี้ไม่ได้ช่วยแก้ไขข้อความที่ตรงกับจุดเริ่มต้นถึงจุดสิ้นสุดดังนั้นพวกเขาจึงไม่ได้รับการปรับปรุงมากนัก
Camille Goudeseune

4
"ถ้า false" มักจะดีกว่าการใส่รหัสความคิดเห็นเพราะจะทำให้แน่ใจได้ว่ารหัสที่แนบมานั้นยังคงเป็นรหัสทางกฎหมาย ข้อแก้ตัวที่ดีที่สุดสำหรับการใส่รหัสความคิดเห็นคือเมื่อจำเป็นต้องลบจริงๆ แต่มีบางสิ่งที่จำเป็นต้องจดจำ - ดังนั้นจึงเป็นเพียงความคิดเห็นและไม่ต้องใช้ "รหัส" อีกต่อไป
Jeff Learman

1
ฉันใช้ความคิดเห็น '#if false;' ด้วยวิธีนี้ฉันสามารถค้นหาและค้นหาทั้งจุดเริ่มต้นและจุดสิ้นสุดของส่วนการลบการดีบัก
Jon

คำตอบนี้ไม่ควร upvoted เนื่องจากไม่ตอบคำถามของ OP ในทางใดทางหนึ่ง
Viktor Joras

54

อาจเป็นประโยชน์สำหรับความต้องการในการดีบักหรือการสาธิต

ฉันพบว่าโซลูชัน Bob Copeland http://bobcopeland.com/blog/2012/10/goto-in-bash/ฉลาด:

#!/bin/bash
# include this boilerplate
function jumpto
{
    label=$1
    cmd=$(sed -n "/$label:/{:a;n;p;ba};" $0 | grep -v ':$')
    eval "$cmd"
    exit
}

start=${1:-"start"}

jumpto $start

start:
# your script goes here...
x=100
jumpto foo

mid:
x=101
echo "This is not printed!"

foo:
x=${x:-10}
echo x is $x

ผลลัพธ์ใน:

$ ./test.sh
x is 100
$ ./test.sh foo
x is 10
$ ./test.sh mid
This is not printed!
x is 101

36
"การสืบเสาะของฉันเพื่อทำให้ทุบตีดูเหมือนภาษาแอสเซมบลีใกล้จะเสร็จสมบูรณ์" - ว้าว. แค่ว้าว
Brian Agnew

5
สิ่งเดียวที่ฉันเปลี่ยนคือทำให้มันเป็นอย่างนั้นเพื่อให้ป้ายกำกับเริ่มต้น: start:เพื่อที่พวกเขาจะได้ไม่ผิดพลาดทางไวยากรณ์
Alexej Magura

5
จะดีกว่าถ้าคุณทำเช่นนั้น: cmd = $ (sed -n "/ # $ label: / {: a; n; p; ba};" $ 0 | grep -v ': $') โดยมีป้ายกำกับเริ่มต้น: # start: => สิ่งนี้จะป้องกันข้อผิดพลาดของสคริปต์
access_granted

2
หืมมันน่าจะเป็นความผิดพลาดของข้าแน่ ๆ ฉันมีโพสต์แก้ไข ขอบคุณ.
Hubbitus

2
set -xช่วยให้เข้าใจว่าเกิดอะไรขึ้น
John Lin

30

คุณสามารถใช้caseใน bash เพื่อจำลอง goto:

#!/bin/bash

case bar in
  foo)
    echo foo
    ;&

  bar)
    echo bar
    ;&

  *)
    echo star
    ;;
esac

ผลิต:

bar
star

4
bash v4.0+โปรดทราบว่านี้ต้อง อย่างไรก็ตามไม่ใช่วัตถุประสงค์ทั่วไปgotoแต่เป็นตัวเลือกการเลื่อนผ่านสำหรับcaseคำสั่ง
mklement0

3
ฉันคิดว่านี่ควรเป็นคำตอบ ฉันมีความต้องการของแท้เพื่อไปที่เพื่อสนับสนุนการดำเนินการสคริปต์ต่อจากคำสั่งที่กำหนด นี่คือในทุก ๆ ด้านยกเว้น semantic, goto, semantics และ syntactic sugars นั้นน่ารัก แต่ไม่จำเป็นเลย ทางออกที่ดี IMO
ธาน g

1
@nathang ไม่ว่าจะเป็นคำตอบขึ้นอยู่กับว่ากรณีของคุณที่เกิดขึ้นกับตาข่ายกับชุดย่อยของกรณีทั่วไป OP ถามเกี่ยวกับ น่าเสียดายที่คำถามถามเกี่ยวกับกรณีทั่วไปทำให้คำตอบนี้แคบเกินไปที่จะถูกต้อง (ไม่ว่าคำถามนั้นควรจะปิดกว้างเกินไปเพราะเหตุผลนั้นคือการอภิปรายที่แตกต่างกัน)
Charles Duffy

1
goto เป็นมากกว่าการเลือก คุณลักษณะ goto หมายถึงสามารถข้ามไปยังสถานที่ตามเงื่อนไขบางอย่างสร้างแม้แต่ลูปอย่างไหล ...
Sergio Abreu

19

หากคุณกำลังทดสอบ / แก้ไขจุดบกพร่องของสคริปต์ทุบตีและเพียงต้องการข้ามไปข้างหน้าผ่านส่วนของรหัสอย่างน้อยหนึ่งรายการต่อไปนี้เป็นวิธีที่ง่ายมากที่จะทำและหาได้ง่ายในภายหลัง (ไม่เหมือนกับวิธีส่วนใหญ่ อธิบายไว้ข้างต้น).

#!/bin/bash

echo "Run this"

cat >/dev/null <<GOTO_1

echo "Don't run this"

GOTO_1

echo "Also run this"

cat >/dev/null <<GOTO_2

echo "Don't run this either"

GOTO_2

echo "Yet more code I want to run"

การวางสคริปต์ของคุณกลับมาเป็นปกติเพียงลบเส้นใด ๆ GOTOกับ

เรายังสามารถพร็อพเพอร์ตี้โซลูชันนี้ได้โดยเพิ่มgotoคำสั่งเป็นนามแฝง:

#!/bin/bash

shopt -s expand_aliases
alias goto="cat >/dev/null <<"

goto GOTO_1

echo "Don't run this"

GOTO_1

echo "Run this"

goto GOTO_2

echo "Don't run this either"

GOTO_2

echo "All done"

นามแฝงมักจะไม่ทำงานในสคริปต์ทุบตีดังนั้นเราจึงต้องการshoptคำสั่งเพื่อแก้ไข

หากคุณต้องการเปิด / ปิดการใช้งานของคุณgotoเราต้องเพิ่มอีกนิด:

#!/bin/bash

shopt -s expand_aliases
if [ -n "$DEBUG" ] ; then
  alias goto="cat >/dev/null <<"
else
  alias goto=":"
fi

goto '#GOTO_1'

echo "Don't run this"

#GOTO1

echo "Run this"

goto '#GOTO_2'

echo "Don't run this either"

#GOTO_2

echo "All done"

จากนั้นคุณสามารถทำได้export DEBUG=TRUEก่อนเรียกใช้สคริปต์

ป้ายกำกับเป็นความคิดเห็นดังนั้นจะไม่ทำให้เกิดข้อผิดพลาดทางไวยากรณ์หากปิดการใช้งานgoto(โดยการตั้งค่าgotoเป็น ' :' ไม่ต้องใช้ op) แต่สิ่งนี้หมายความว่าเราต้องอ้างข้อความเหล่านั้นในgotoงบของเรา

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


คำตอบของลอเรนซ์นั้นเจ๋งเกินไป คุณได้รับคะแนนของฉัน
Mogens TrasherDK

1
มันเหมือนกับการข้ามไปif(false)ดูเหมือนว่าจะสมเหตุสมผลมากกว่า (สำหรับฉัน)
vesperto

2
การอ้างถึง "ฉลาก" ของ goto ยังหมายความว่า here-doc ไม่ได้ถูกขยาย / ประเมินผลซึ่งช่วยให้คุณประหยัดจากการหาบั๊กที่ยาก (ไม่ได้กล่าวถึงมันจะขึ้นอยู่กับ: การขยายพารามิเตอร์การทดแทนคำสั่งและการขยายเลขคณิต ผลข้างเคียง). คุณยังสามารถปรับแต่งสิ่งนี้เล็กน้อยด้วยalias goto=":<<"และแจกจ่ายพร้อมcatกันทั้งหมด
mr.spuratic

ใช่, เวสเปอร์โต, คุณสามารถใช้คำสั่ง 'if', และฉันทำไปแล้วในสคริปต์หลาย ๆ อัน, แต่มันยุ่งเหยิงมากและยากที่จะควบคุมและติดตามโดยเฉพาะอย่างยิ่งถ้าคุณต้องการเปลี่ยนจุดกระโดดบ่อยๆ
Laurence Renshaw

12

แม้ว่าคนอื่นจะชี้แจงแล้วว่าไม่มีการgotoเทียบเท่าโดยตรงในทุบตี (และให้ทางเลือกที่ใกล้เคียงที่สุดเช่นฟังก์ชั่น, ลูปและตัวแบ่ง) ฉันต้องการแสดงให้เห็นว่าการใช้ลูป plus breakสามารถจำลองคำสั่ง goto ประเภทใด

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

#!/bin/bash

TestIP="8.8.8.8"

# Loop forever (until break is issued)
while true; do

    # Do a simple test for Internet connectivity
    PacketLoss=$(ping "$TestIP" -c 2 | grep -Eo "[0-9]+% packet loss" | grep -Eo "^[0-9]")

    # Exit the loop if ping is no longer dropping packets
    if [ "$PacketLoss" == 0 ]; then
        echo "Connection restored"
        break
    else
        echo "No connectivity"
    fi
done

7

วิธีนี้มีปัญหาต่อไปนี้:

  • การลบบรรทัดรหัสทั้งหมดที่ลงท้ายด้วย a :
  • ปฏิบัติlabel:ที่ใดก็ได้ในบรรทัดเป็นป้ายกำกับ

นี่คือรุ่นที่คงที่ ( shell-checkสะอาด):


#!/bin/bash

# GOTO for bash, based upon https://stackoverflow.com/a/31269848/5353461
function goto
{
 local label=$1
 cmd=$(sed -En "/^[[:space:]]*#[[:space:]]*$label:[[:space:]]*#/{:a;n;p;ba};" "$0")
 eval "$cmd"
 exit
}

start=${1:-start}
goto "$start"  # GOTO start: by default

#start:#  Comments can occur after labels
echo start
goto end

  # skip: #  Whitespace is allowed
echo this is usually skipped

# end: #
echo end

6

trapมีอีกหนึ่งความสามารถในการบรรลุผลลัพธ์ที่ต้องการคือคำสั่ง มันสามารถใช้เพื่อวัตถุประสงค์ในการทำความสะอาดเช่น


4

ไม่มีการgotoทุบตี

นี่คือวิธีแก้ไขปัญหาสกปรกโดยใช้การtrapกระโดดไปข้างหลังเท่านั้น :)

#!/bin/bash -e
trap '
echo I am
sleep 1
echo here now.
' EXIT

echo foo
goto trap 2> /dev/null
echo bar

เอาท์พุท:

$ ./test.sh 
foo
I am
here now.

สิ่งนี้ไม่ควรใช้ในวิธีนั้น แต่ใช้เพื่อการศึกษาเท่านั้น นี่คือสาเหตุที่ใช้งานได้:

trapใช้การจัดการข้อยกเว้นเพื่อให้เกิดการเปลี่ยนแปลงในการไหลของรหัส ในกรณีนี้การtrapจับอะไรที่ทำให้สคริปต์ออก คำสั่งgotoไม่มีอยู่และด้วยเหตุนี้จะเกิดข้อผิดพลาดซึ่งโดยปกติจะออกจากสคริปต์ ข้อผิดพลาดนี้กำลังถูกจับtrapและ2>/dev/nullซ่อนข้อความแสดงข้อผิดพลาดที่จะแสดงตามปกติ

การใช้งานของ goto นี้ไม่น่าเชื่อถือเนื่องจากคำสั่งที่ไม่มีอยู่จริง (หรือข้อผิดพลาดอื่น ๆ สำหรับลักษณะนั้น) จะดำเนินการคำสั่ง trap เดียวกัน โดยเฉพาะคุณไม่สามารถเลือกป้ายกำกับที่จะไปได้


โดยทั่วไปในสถานการณ์จริงที่คุณไม่จำเป็นต้องมีคำสั่ง goto ซ้ำซ้อนเพราะการโทรแบบสุ่มไปยังสถานที่ต่าง ๆ ทำให้รหัสของคุณยากต่อการเข้าใจ

หากรหัสของคุณจะถูกเรียกหลายครั้งแล้วพิจารณาที่จะใช้ห่วงและการเปลี่ยนแปลงขั้นตอนการทำงานในการใช้งานและcontinuebreak

หากรหัสของคุณซ้ำตัวเองลองเขียนฟังก์ชั่นและเรียกมันหลาย ๆ ครั้งตามที่คุณต้องการ

หากรหัสของคุณจำเป็นต้องข้ามไปยังส่วนที่เฉพาะเจาะจงขึ้นอยู่กับค่าตัวแปรแล้วพิจารณาใช้caseคำสั่ง

หากคุณสามารถแยกรหัสยาว ๆ ของคุณออกเป็นชิ้นเล็ก ๆ ให้พิจารณาย้ายมันเป็นไฟล์แยกกันและเรียกมันจากสคริปต์หลัก


ความแตกต่างระหว่างแบบฟอร์มนี้กับฟังก์ชั่นปกติคืออะไร?
yurenchen

2
@ yurenchen - คิดว่าtrapใช้exception handlingเพื่อให้เกิดการเปลี่ยนแปลงในการไหลของรหัส ในกรณีนี้ดักจับอะไรที่เป็นสาเหตุของสคริปต์เพื่อที่จะถูกเรียกโดยการเรียกใช้คำสั่งที่ไม่มีอยู่จริงEXIT gotoBTW: การโต้แย้งgoto trapอาจเป็นอะไรก็ได้goto ignoredเพราะมันเป็นgotoสาเหตุของการออกและ2>/dev/nullซ่อนข้อความแสดงข้อผิดพลาดที่บอกว่าสคริปต์ของคุณกำลังออก
Jesse Chisholm

2

นี่คือการแก้ไขเล็กน้อยของสคริปต์ Judy Schmidt ที่ Hubbbitus นำเสนอ

การวางป้ายกำกับที่ไม่ใช้ Escape ในสคริปต์เป็นปัญหาบนเครื่องและทำให้เกิดปัญหาขัดข้อง สิ่งนี้ง่ายพอที่จะแก้ไขได้โดยการเพิ่ม # เพื่อหลีกเลี่ยงป้ายกำกับ ขอบคุณ Alexej Magura และ access_granted สำหรับคำแนะนำของพวกเขา

#!/bin/bash
# include this boilerplate
function goto {  
label=$1
cmd=$(sed -n "/$#label#:/{:a;n;p;ba};" $0 | grep -v ':$')
eval "$cmd"
exit
}

start=${1:-"start"}

goto $start

#start#
echo "start"
goto bing

#boom#
echo boom
goto eof

#bang#
echo bang
goto boom

#bing#
echo bing
goto bang

#eof#
echo "the end mother-hugger..."

วางสำเนานี้ไม่ทำงาน => ยังมี jumpto
Alexis Paques

นั่นหมายความว่าอย่างไร? ไม่ทำงานอะไร คุณเจาะจงมากกว่านี้ไหม?
thebunnyrules

แน่นอนฉันลองใช้รหัสแล้ว! ฉันทดสอบภายใต้เงื่อนไขที่แตกต่างกัน 5 หรือ 6 ข้อก่อนโพสต์ข้อมูลทั้งหมดสำเร็จ รหัสล้มเหลวสำหรับคุณข้อความข้อผิดพลาดหรือรหัสอะไร?
thebunnyrules

ไม่ว่ามนุษย์คนไหน ฉันต้องการช่วยคุณ แต่คุณเป็นคนที่คลุมเครือและไม่พูดจริง (ไม่พูดถึงการดูถูกคำถามที่ว่า "คุณทดสอบแล้ว") "คุณไม่ได้วางอย่างถูกต้องหมายความว่า"? หากคุณอ้างถึง "/ $ # label #: / {: a; n; p; ba};" ฉันรู้ว่ามันแตกต่างกัน ฉันแก้ไขมันสำหรับรูปแบบป้ายกำกับใหม่ (aka # label # vs: label ในคำตอบอื่นซึ่งเป็นสคริปต์การทำงานล้มเหลวในบางกรณี) คุณมีปัญหาที่ถูกต้องกับคำตอบของฉัน (เช่นสคริปต์ผิดพลาดหรือไวยากรณ์ที่ไม่ดี) หรือคุณเพียงแค่ -1 คำตอบของฉันเพราะคุณคิดว่า "ฉันไม่ทราบวิธีการตัดและวาง"
thebunnyrules

1
@thebunnyrules ฉันพบปัญหาเดียวกันกับคุณ แต่ได้แก้ไข +1
Fabby

2

goto ที่ค้นหาได้ง่ายสำหรับการใช้ความคิดเห็นในการบล็อกโค้ดเมื่อทำการดีบั๊ก

GOTO=false
if ${GOTO}; then
    echo "GOTO failed"
    ...
fi # End of GOTO
echo "GOTO done"

ผลลัพธ์คือ -> GOTO เสร็จแล้ว


1

ฉันพบวิธีการทำสิ่งนี้โดยใช้ฟังก์ชั่น

กล่าวว่าสำหรับตัวอย่างเช่นคุณมี 3 ทางเลือก: A, และB และดำเนินการคำสั่ง แต่ให้ข้อมูลเพิ่มเติมแก่คุณและนำคุณไปยังพรอมต์ดั้งเดิมอีกครั้ง สิ่งนี้สามารถทำได้โดยใช้ฟังก์ชั่นCABC

โปรดทราบว่าเนื่องจากการต่อบรรทัดfunction demoFunctionนั้นเป็นเพียงการตั้งค่าฟังก์ชั่นคุณจะต้องเรียกใช้demoFunctionสคริปต์หลังจากนั้นดังนั้นฟังก์ชันจะทำงานจริง

คุณสามารถดัดแปลงสิ่งนี้ได้ง่าย ๆ โดยการเขียนฟังก์ชั่นอื่น ๆ และเรียกพวกเขาถ้าคุณต้องการที่GOTOอื่นในสคริปต์เชลล์

function demoFunction {
        read -n1 -p "Pick a letter to run a command [A, B, or C for more info] " runCommand

        case $runCommand in
            a|A) printf "\n\tpwd being executed...\n" && pwd;;
            b|B) printf "\n\tls being executed...\n" && ls;;
            c|C) printf "\n\toption A runs pwd, option B runs ls\n" && demoFunction;;
        esac
}

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