Tidak, tidak ada gotodi bash (setidaknya katanya command not founduntuk saya). Mengapa? Kemungkinan ada cara yang lebih baik untuk melakukannya.
Niklas B.
153
Dia mungkin punya alasan. Saya menemukan pertanyaan ini karena saya ingin gotopernyataan untuk melewatkan banyak kode untuk debugging skrip besar tanpa menunggu satu jam untuk menyelesaikan berbagai tugas yang tidak berhubungan. Saya tentu saja tidak menggunakan gotokode produksi, tetapi untuk debug kode saya, itu akan membuat hidup saya jauh lebih mudah, dan akan lebih mudah dikenali ketika datang untuk menghapusnya.
Karl Nicoll
30
@delnan Tapi tidak punya goto bisa membuat beberapa hal lebih rumit. Memang ada use case.
glglgl
71
Saya muak dengan mitos goto ini! Tidak ada yang salah dengan goto! Semua yang Anda tulis akhirnya menjadi kebohongan. Di assembler, hanya ada goto. Alasan yang baik untuk menggunakan goto dalam bahasa pemrograman yang lebih tinggi adalah misalnya melompat keluar dari loop bersarang dengan cara yang bersih dan mudah dibaca.
Alexander Czutro
25
"Hindari goto" adalah aturan yang bagus. Seperti aturan apa pun, itu harus dipelajari dalam tiga fase. Pertama: ikuti aturan sampai itu sifat kedua. Kedua, belajar memahami alasan aturan tersebut. Ketiga, pelajari pengecualian yang baik untuk aturan tersebut, berdasarkan pada pemahaman yang komprehensif tentang cara mengikuti aturan dan alasan aturan tersebut. Hindari melewatkan langkah-langkah di atas, yang akan seperti menggunakan "goto". ;-)
Jeff Learman
Jawaban:
75
Tidak, tidak ada; melihat §3.2.4 "Compound Perintah" di Bash Reference Manual untuk informasi tentang struktur kontrol yang melakukan eksis. Secara khusus, perhatikan penyebutan breakdan continue, yang tidak sefleksibel goto, tetapi lebih fleksibel dalam Bash daripada dalam beberapa bahasa, dan dapat membantu Anda mencapai apa yang Anda inginkan. (Apa pun yang Anda inginkan ...)
Bisakah Anda memperluas "lebih fleksibel dalam Bash daripada dalam beberapa bahasa"?
user239558
21
@ user239558: Beberapa bahasa hanya memungkinkan Anda untuk breakatau continuedari loop paling dalam, sedangkan Bash memungkinkan Anda menentukan berapa level loop untuk dilompati. (Dan bahkan bahasa yang memungkinkan Anda untuk breakatau continuedari loop sewenang-wenang, sebagian besar mengharuskan itu untuk diekspresikan secara statis - misalnya, break foo;akan keluar dari loop berlabel foo- sedangkan di Bash itu diekspresikan secara dinamis - misalnya, break "$foo"akan keluar dari $fooloop. )
ruakh
Saya akan merekomendasikan mendefinisikan fungsi dengan fitur-fitur yang diperlukan dan caling mereka dari bagian lain dari kode.
Blmayer
@ruakh Sebenarnya, banyak bahasa memungkinkan break LABEL_NAME;, alih-alih Bash menjijikkan break INTEGER;.
Sapphire_Brick
1
@ Safhire_Brick: Ya, saya menyebutkan itu di komentar yang Anda balas.
ruakh
124
Jika Anda menggunakannya untuk melewatkan bagian dari skrip besar untuk debugging (lihat komentar Karl Nicoll), maka jika false bisa menjadi pilihan yang baik (tidak yakin apakah "false" selalu tersedia, bagi saya itu di / bin / false) :
# ... Code I want to run here ...if false;then# ... Code I want to skip here ...fi# ... I want to resume here ...
Kesulitan muncul ketika saatnya untuk merobek kode debug Anda. Konstruk "jika salah" cukup mudah dan mudah diingat, tetapi bagaimana Anda menemukan fi yang cocok? Jika editor Anda memungkinkan Anda untuk memblokir indentasi, Anda bisa membuat indentasi blok yang dilompati (maka Anda ingin mengembalikannya setelah selesai). Atau komentar pada baris fi, tetapi itu harus menjadi sesuatu yang Anda akan ingat, yang saya duga akan sangat tergantung pada programmer.
Ya falseselalu tersedia. Tetapi jika Anda memiliki blok kode yang tidak ingin Anda jalankan, cukup beri komentar. Atau hapus (dan lihat di sistem kontrol sumber Anda jika Anda perlu memulihkannya nanti).
Keith Thompson
1
Jika blok kode terlalu panjang untuk mengomentari satu baris sekaligus, lihat trik ini. stackoverflow.com/questions/947897/… Namun, ini tidak membantu editor teks cocok dengan awal sampai akhir, jadi, mereka tidak banyak perbaikan.
Camille Goudeseune
4
"if false" seringkali jauh lebih baik daripada mengomentari kode, karena memastikan bahwa kode terlampir tetap menjadi kode hukum. Alasan terbaik untuk berkomentar kode adalah ketika itu benar-benar perlu dihapus, tetapi ada sesuatu yang perlu diingat - jadi itu hanya komentar, dan tidak lagi "kode".
Jeff Learman
1
Saya menggunakan komentar '#jika salah;'. Dengan begitu saya bisa mencari itu dan menemukan bagian awal dan akhir dari bagian penghapusan debug.
Jon
Jawaban ini seharusnya tidak dibatalkan karena tidak menanggapi pertanyaan OP dengan cara apa pun.
Viktor Joras
54
Ini memang mungkin berguna untuk beberapa kebutuhan debug atau demonstrasi.
"Pencarian saya untuk membuat bash terlihat seperti bahasa majelis semakin dekat ke selesai." - Wow. Cuma wow.
Brian Agnew
5
satu-satunya hal yang saya ubah adalah membuatnya sehingga label mulai seperti sehingga : start:mereka tidak kesalahan sintaks.
Alexej Magura
5
Akan lebih baik jika Anda melakukan itu: cmd = $ (sed -n "/ # $ label: / {: a; n; p; ba};" $ 0 | grep -v ': $') dengan label yang dimulai dengan: # mulai: => ini akan mencegah kesalahan skrip
access_granted
2
Hm, memang itu kemungkinan besar kesalahan saya. Saya sudah mengedit posting. Terima kasih.
Hubbitus
2
set -xmembantu memahami apa yang terjadi
John Lin
30
Anda dapat menggunakan casebash untuk mensimulasikan goto:
#!/bin/bashcase bar in
foo)
echo foo
;&
bar)
echo bar
;&*)
echo star
;;esac
Perhatikan bahwa ini memerlukan bash v4.0+. Namun, ini bukan tujuan umum gototetapi pilihan untuk menerobos casepernyataan tersebut.
mklement0
3
Saya pikir ini harus menjadi jawabannya. Saya memiliki kebutuhan yang tulus untuk pergi ke dalam rangka mendukung kelanjutan pelaksanaan skrip, dari instruksi yang diberikan. ini, dalam segala hal, tetapi semantik, goto, dan semantik dan gula sintaksis lucu, tetapi tidak sepenuhnya diperlukan. solusi hebat, IMO.
nathan g
1
@nathang, apakah itu yang jawabannya tergantung pada apakah kasus Anda kebetulan mesh dengan subset dari kasus umum OP bertanya tentang. Sayangnya, pertanyaannya tentang kasus umum, membuat jawaban ini terlalu sempit untuk menjadi benar. (Apakah pertanyaan itu harus ditutup terlalu luas karena alasan itu adalah diskusi yang berbeda).
Charles Duffy
1
goto lebih dari sekadar memilih. fitur goto berarti dapat melompat ke tempat-tempat berdasarkan beberapa kondisi, bahkan membuat loop seperti aliran ...
Sergio Abreu
19
Jika Anda menguji / men-debug skrip bash, dan hanya ingin melompati maju melewati satu atau lebih bagian kode, berikut ini adalah cara yang sangat sederhana untuk melakukannya yang juga sangat mudah ditemukan dan dihapus nanti (tidak seperti kebanyakan metode lainnya) dijelaskan di atas).
#!/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"
Untuk mengembalikan script Anda ke normal, cukup hapus baris apa saja dengan GOTO.
Kami juga dapat melakukan prettify solusi ini, dengan menambahkan gotoperintah sebagai alias:
#!/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"
Alias biasanya tidak bekerja dalam skrip bash, jadi kita perlu shoptperintah untuk memperbaikinya.
Jika Anda ingin dapat mengaktifkan / menonaktifkan Anda goto, kami perlu sedikit lebih banyak:
#!/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"
Kemudian bisa Anda lakukan export DEBUG=TRUEsebelum menjalankan skrip.
Label adalah komentar, jadi tidak akan menyebabkan kesalahan sintaks jika menonaktifkan milik kita goto(dengan mengatur gotoke :no-op), tetapi ini berarti kita perlu mengutipnya digoto pernyataan .
Setiap kali menggunakan gotosolusi apa pun , Anda harus berhati-hati bahwa kode yang Anda lewati tidak menetapkan variabel apa pun yang Anda andalkan nanti - Anda mungkin perlu memindahkan definisi tersebut ke bagian atas skrip Anda, atau tepat di atas yang lain gotopernyataan Anda .
Tanpa masuk ke kebaikan / keburukan goto, solusi Laurence itu keren. Anda mendapat suara saya.
Mogens TrasherDK
1
Itu lebih seperti sebuah loncatan, yang if(false)tampaknya lebih masuk akal (bagi saya).
vesperto
2
Mengutip "label" goto juga berarti bahwa di sini-doc tidak diperluas / dievaluasi yang menyelamatkan Anda dari beberapa kesulitan untuk menemukan bug (tidak dikutip, itu akan tunduk pada: ekspansi parameter, penggantian perintah, dan ekspansi aritmatika, yang semuanya dapat memiliki efek samping). Anda juga dapat mengubah sedikit alias goto=":<<"dan membuangnyacat semuanya.
mr.spuratic
ya, vesperto, Anda dapat menggunakan pernyataan 'jika', dan saya telah melakukannya dalam banyak skrip, tetapi itu menjadi sangat berantakan dan jauh lebih sulit untuk dikendalikan dan dilacak, terutama jika Anda ingin sering mengubah titik lompatan Anda.
Laurence Renshaw
12
Meskipun yang lain sudah mengklarifikasi bahwa tidak ada gotopadanan langsung dalam bash (dan memberikan alternatif terdekat seperti fungsi, loop, dan break), saya ingin menggambarkan bagaimana menggunakan loop plus breakdapat mensimulasikan jenis pernyataan goto tertentu.
Situasi di mana saya menemukan ini yang paling berguna adalah ketika saya harus kembali ke awal bagian kode jika kondisi tertentu tidak terpenuhi. Dalam contoh di bawah ini, loop sementara akan berjalan selamanya sampai ping berhenti menjatuhkan paket ke IP tes.
#!/bin/bashTestIP="8.8.8.8"# Loop forever (until break is issued)while true;do# Do a simple test for Internet connectivityPacketLoss=$(ping "$TestIP"-c 2| grep -Eo"[0-9]+% packet loss"| grep -Eo"^[0-9]")# Exit the loop if ping is no longer dropping packetsif["$PacketLoss"==0];then
echo "Connection restored"breakelse
echo "No connectivity"fidone
#!/bin/bash# GOTO for bash, based upon https://stackoverflow.com/a/31269848/5353461function 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
Berikut adalah beberapa solusi kotor menggunakan trapyang melompat hanya mundur :)
#!/bin/bash -e
trap '
echo I am
sleep 1
echo here now.
' EXIT
echo foo
goto trap 2>/dev/null
echo bar
Keluaran:
$ ./test.sh
foo
I am
here now.
Ini tidak boleh digunakan dengan cara itu, tetapi hanya untuk tujuan pendidikan. Inilah mengapa ini bekerja:
trapmenggunakan penanganan pengecualian untuk mencapai perubahan dalam aliran kode. Dalam hal trapini menangkap apa pun yang menyebabkan skrip EXIT. Perintah gototidak ada, dan karenanya mengeluarkan kesalahan, yang biasanya akan keluar dari skrip. Kesalahan ini ditangkap trap, dan2>/dev/null menyembunyikan pesan kesalahan yang biasanya ditampilkan.
Implementasi goto ini jelas tidak dapat diandalkan, karena perintah yang tidak ada (atau kesalahan lainnya, dengan cara itu), akan menjalankan perintah perangkap yang sama. Khususnya, Anda tidak dapat memilih label mana yang akan dikunjungi.
Pada dasarnya dalam skenario nyata Anda tidak memerlukan pernyataan goto, itu berlebihan karena panggilan acak ke tempat yang berbeda hanya membuat kode Anda sulit dimengerti.
Jika kode Anda dipanggil berkali-kali, maka pertimbangkan untuk menggunakan loop dan mengubah alur kerjanya untuk menggunakan continuedan break.
Jika kode Anda berulang, pertimbangkan untuk menulis fungsi dan memanggilnya sebanyak yang Anda inginkan.
Jika kode Anda perlu melompat ke bagian tertentu berdasarkan nilai variabel, maka pertimbangkan untuk menggunakan casepernyataan.
Jika Anda dapat memisahkan kode panjang Anda menjadi potongan-potongan kecil, pertimbangkan untuk memindahkannya ke file terpisah dan memanggilnya dari skrip induk.
apa perbedaan antara formulir ini dan fungsi normal?
yurenchen
2
@Yurenchen - Pikirkan trapsebagai gunakan exception handlinguntuk mencapai perubahan dalam aliran kode. Dalam hal ini jebakan menangkap apa pun yang menyebabkan skrip EXIT, yang dipicu oleh menjalankan perintah yang tidak ada goto. BTW: Argumennya goto trapbisa apa saja, goto ignoredkarena itu gotoyang menyebabkan EXIT, dan 2>/dev/nullmenyembunyikan pesan kesalahan yang mengatakan skrip Anda keluar.
Jesse Chisholm
2
Ini adalah koreksi kecil dari naskah Judy Schmidt yang diajukan oleh Hubbbitus.
Menempatkan label yang tidak diloloskan dalam skrip bermasalah pada mesin dan menyebabkannya macet. Ini cukup mudah untuk diselesaikan dengan menambahkan # untuk keluar dari label. Terima kasih kepada Alexej Magura dan access_granted atas saran mereka.
#!/bin/bash# include this boilerplatefunction 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..."
Salin tempel ini tidak berfungsi => masih ada lompatan.
Alexis Paques
Apa artinya? Apa yang tidak berfungsi? Bisakah kamu lebih spesifik?
thebunnyrules
Tentu saja saya mencoba kodenya! Saya menguji di bawah 5 atau 6 kondisi yang berbeda sebelum memposting semua berhasil. Bagaimana kode gagal untuk Anda, pesan atau kode kesalahan apa?
thebunnyrules
Pria apa pun. Saya ingin membantu Anda tetapi Anda benar-benar kabur dan tidak berkomunikasi (belum lagi menghina dengan pertanyaan "apakah Anda mengujinya"). Apa artinya "Anda tidak menempel dengan benar"? Jika Anda merujuk pada label "/ $ # #: / {: a; n; p; ba};" sebagian, saya sangat sadar bahwa itu berbeda. Saya memodifikasinya untuk format label baru (alias # label # vs: label di jawaban lain yang mengalami crash script dalam beberapa kasus). Apakah Anda memiliki masalah yang valid dengan jawaban saya (seperti script crash atau sintaksis buruk) atau apakah Anda hanya -1 jawaban saya karena Anda berpikir "Saya tidak tahu cara memotong dan menempel"?
Saya menemukan cara untuk melakukan ini menggunakan fungsi.
Katakanlah, misalnya, Anda memiliki 3 pilihan: A, B, dan C. Adan Bjalankan perintah, tetapi Cmemberi Anda lebih banyak info dan membawa Anda ke prompt asli lagi. Ini bisa dilakukan menggunakan fungsi.
Perhatikan bahwa karena baris containg function demoFunctionhanya mengatur fungsi, Anda perlu memanggil demoFunctionskrip tersebut sehingga fungsi tersebut benar-benar akan berjalan.
Anda dapat dengan mudah mengadaptasi ini dengan menulis beberapa fungsi lain dan memanggilnya jika Anda perlu " GOTO" tempat lain di skrip shell Anda.
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
goto
di bash (setidaknya katanyacommand not found
untuk saya). Mengapa? Kemungkinan ada cara yang lebih baik untuk melakukannya.goto
pernyataan untuk melewatkan banyak kode untuk debugging skrip besar tanpa menunggu satu jam untuk menyelesaikan berbagai tugas yang tidak berhubungan. Saya tentu saja tidak menggunakangoto
kode produksi, tetapi untuk debug kode saya, itu akan membuat hidup saya jauh lebih mudah, dan akan lebih mudah dikenali ketika datang untuk menghapusnya.Jawaban:
Tidak, tidak ada; melihat §3.2.4 "Compound Perintah" di Bash Reference Manual untuk informasi tentang struktur kontrol yang melakukan eksis. Secara khusus, perhatikan penyebutan
break
dancontinue
, yang tidak sefleksibelgoto
, tetapi lebih fleksibel dalam Bash daripada dalam beberapa bahasa, dan dapat membantu Anda mencapai apa yang Anda inginkan. (Apa pun yang Anda inginkan ...)sumber
break
ataucontinue
dari loop paling dalam, sedangkan Bash memungkinkan Anda menentukan berapa level loop untuk dilompati. (Dan bahkan bahasa yang memungkinkan Anda untukbreak
ataucontinue
dari loop sewenang-wenang, sebagian besar mengharuskan itu untuk diekspresikan secara statis - misalnya,break foo;
akan keluar dari loop berlabelfoo
- sedangkan di Bash itu diekspresikan secara dinamis - misalnya,break "$foo"
akan keluar dari$foo
loop. )break LABEL_NAME;
, alih-alih Bash menjijikkanbreak INTEGER;
.Jika Anda menggunakannya untuk melewatkan bagian dari skrip besar untuk debugging (lihat komentar Karl Nicoll), maka jika false bisa menjadi pilihan yang baik (tidak yakin apakah "false" selalu tersedia, bagi saya itu di / bin / false) :
Kesulitan muncul ketika saatnya untuk merobek kode debug Anda. Konstruk "jika salah" cukup mudah dan mudah diingat, tetapi bagaimana Anda menemukan fi yang cocok? Jika editor Anda memungkinkan Anda untuk memblokir indentasi, Anda bisa membuat indentasi blok yang dilompati (maka Anda ingin mengembalikannya setelah selesai). Atau komentar pada baris fi, tetapi itu harus menjadi sesuatu yang Anda akan ingat, yang saya duga akan sangat tergantung pada programmer.
sumber
false
selalu tersedia. Tetapi jika Anda memiliki blok kode yang tidak ingin Anda jalankan, cukup beri komentar. Atau hapus (dan lihat di sistem kontrol sumber Anda jika Anda perlu memulihkannya nanti).Ini memang mungkin berguna untuk beberapa kebutuhan debug atau demonstrasi.
Saya menemukan bahwa solusi Bob Copeland http://bobcopeland.com/blog/2012/10/goto-in-bash/ elegan:
menghasilkan:
sumber
: start:
mereka tidak kesalahan sintaks.set -x
membantu memahami apa yang terjadiAnda dapat menggunakan
case
bash untuk mensimulasikan goto:menghasilkan:
sumber
bash v4.0+
. Namun, ini bukan tujuan umumgoto
tetapi pilihan untuk meneroboscase
pernyataan tersebut.Jika Anda menguji / men-debug skrip bash, dan hanya ingin melompati maju melewati satu atau lebih bagian kode, berikut ini adalah cara yang sangat sederhana untuk melakukannya yang juga sangat mudah ditemukan dan dihapus nanti (tidak seperti kebanyakan metode lainnya) dijelaskan di atas).
Untuk mengembalikan script Anda ke normal, cukup hapus baris apa saja dengan
GOTO
.Kami juga dapat melakukan prettify solusi ini, dengan menambahkan
goto
perintah sebagai alias:Alias biasanya tidak bekerja dalam skrip bash, jadi kita perlu
shopt
perintah untuk memperbaikinya.Jika Anda ingin dapat mengaktifkan / menonaktifkan Anda
goto
, kami perlu sedikit lebih banyak:Kemudian bisa Anda lakukan
export DEBUG=TRUE
sebelum menjalankan skrip.Label adalah komentar, jadi tidak akan menyebabkan kesalahan sintaks jika menonaktifkan milik kita
goto
(dengan mengaturgoto
ke:
no-op), tetapi ini berarti kita perlu mengutipnya digoto
pernyataan .Setiap kali menggunakan
goto
solusi apa pun , Anda harus berhati-hati bahwa kode yang Anda lewati tidak menetapkan variabel apa pun yang Anda andalkan nanti - Anda mungkin perlu memindahkan definisi tersebut ke bagian atas skrip Anda, atau tepat di atas yang laingoto
pernyataan Anda .sumber
if(false)
tampaknya lebih masuk akal (bagi saya).alias goto=":<<"
dan membuangnyacat
semuanya.Meskipun yang lain sudah mengklarifikasi bahwa tidak ada
goto
padanan langsung dalam bash (dan memberikan alternatif terdekat seperti fungsi, loop, dan break), saya ingin menggambarkan bagaimana menggunakan loop plusbreak
dapat mensimulasikan jenis pernyataan goto tertentu.Situasi di mana saya menemukan ini yang paling berguna adalah ketika saya harus kembali ke awal bagian kode jika kondisi tertentu tidak terpenuhi. Dalam contoh di bawah ini, loop sementara akan berjalan selamanya sampai ping berhenti menjatuhkan paket ke IP tes.
sumber
Solusi ini memiliki masalah berikut:
:
label:
mana saja pada garis sebagai labelIni versi tetap (
shell-check
bersih):sumber
Ada satu lagi kemampuan untuk mencapai hasil yang diinginkan: perintah
trap
. Ini dapat digunakan untuk membersihkan tujuan misalnya.sumber
Tidak ada
goto
di bash.Berikut adalah beberapa solusi kotor menggunakan
trap
yang melompat hanya mundur :)Keluaran:
Ini tidak boleh digunakan dengan cara itu, tetapi hanya untuk tujuan pendidikan. Inilah mengapa ini bekerja:
trap
menggunakan penanganan pengecualian untuk mencapai perubahan dalam aliran kode. Dalam haltrap
ini menangkap apa pun yang menyebabkan skrip EXIT. Perintahgoto
tidak ada, dan karenanya mengeluarkan kesalahan, yang biasanya akan keluar dari skrip. Kesalahan ini ditangkaptrap
, dan2>/dev/null
menyembunyikan pesan kesalahan yang biasanya ditampilkan.Implementasi goto ini jelas tidak dapat diandalkan, karena perintah yang tidak ada (atau kesalahan lainnya, dengan cara itu), akan menjalankan perintah perangkap yang sama. Khususnya, Anda tidak dapat memilih label mana yang akan dikunjungi.
Pada dasarnya dalam skenario nyata Anda tidak memerlukan pernyataan goto, itu berlebihan karena panggilan acak ke tempat yang berbeda hanya membuat kode Anda sulit dimengerti.
Jika kode Anda dipanggil berkali-kali, maka pertimbangkan untuk menggunakan loop dan mengubah alur kerjanya untuk menggunakan
continue
danbreak
.Jika kode Anda berulang, pertimbangkan untuk menulis fungsi dan memanggilnya sebanyak yang Anda inginkan.
Jika kode Anda perlu melompat ke bagian tertentu berdasarkan nilai variabel, maka pertimbangkan untuk menggunakan
case
pernyataan.Jika Anda dapat memisahkan kode panjang Anda menjadi potongan-potongan kecil, pertimbangkan untuk memindahkannya ke file terpisah dan memanggilnya dari skrip induk.
sumber
trap
sebagai gunakanexception handling
untuk mencapai perubahan dalam aliran kode. Dalam hal ini jebakan menangkap apa pun yang menyebabkan skripEXIT
, yang dipicu oleh menjalankan perintah yang tidak adagoto
. BTW: Argumennyagoto trap
bisa apa saja,goto ignored
karena itugoto
yang menyebabkan EXIT, dan2>/dev/null
menyembunyikan pesan kesalahan yang mengatakan skrip Anda keluar.Ini adalah koreksi kecil dari naskah Judy Schmidt yang diajukan oleh Hubbbitus.
Menempatkan label yang tidak diloloskan dalam skrip bermasalah pada mesin dan menyebabkannya macet. Ini cukup mudah untuk diselesaikan dengan menambahkan # untuk keluar dari label. Terima kasih kepada Alexej Magura dan access_granted atas saran mereka.
sumber
Sebuah goto yang mudah dicari untuk penggunaan mengomentari blok kode saat debugging.
Hasilnya adalah-> GOTO selesai
sumber
Saya menemukan cara untuk melakukan ini menggunakan fungsi.
Katakanlah, misalnya, Anda memiliki 3 pilihan:
A
,B
, danC
.A
danB
jalankan perintah, tetapiC
memberi Anda lebih banyak info dan membawa Anda ke prompt asli lagi. Ini bisa dilakukan menggunakan fungsi.Perhatikan bahwa karena baris containg
function demoFunction
hanya mengatur fungsi, Anda perlu memanggildemoFunction
skrip tersebut sehingga fungsi tersebut benar-benar akan berjalan.Anda dapat dengan mudah mengadaptasi ini dengan menulis beberapa fungsi lain dan memanggilnya jika Anda perlu "
GOTO
" tempat lain di skrip shell Anda.sumber