Apa yang setara dengan && saat menulis skrip bash?


31

Saya minta maaf sebelumnya jika ini adalah pertanyaan rangkap. Saya memang berusaha mencari / memeriksa sebelum bertanya di sini.

Saya nyaman menulis satu kalimat seperti ini:

foocommand && foocommand2 && foocommand3

Gagasannya adalah bahwa saya hanya ingin menjalankan perintah selanjutnya jika yang sebelumnya "berhasil".

Saya sedang menulis skrip yang agak panjang dan one-liner ini tidak layak karena terlihat seperti blok kode yang membingungkan bagi semua orang.

Saya ingin menghapus perintah dan menulis komentar di antara mereka dalam skrip. Bagaimana saya bisa melakukan ini dan masih memiliki yang setara dengan && di sana?


4
Beruang ini mengulangi: &&tidak berarti perintah berikutnya akan berjalan jika sebelumnya satu berhasil. Ini berarti perintah akan berjalan jika hasil kolektif dari semua perintah sebelumnya dalam daftar perintah berhasil. Anda mungkin tahu ini, tetapi pembaca di masa depan mungkin salah paham.
kojiro

1
Juga hanya sebagai catatan, perilaku yang Anda gambarkan ini berasal dari ||dan &&(sebagai lawan |atau &) disebut hubungan pendek. Perilaku yang digunakan dengan operator terakhir disebut evaluasi bersemangat.
AndyPerfect

7
@ Kojiro: Saya tidak melihat perbedaannya. a && b && chanya akan berjalan bjika aberhasil, jadi "itu hanya berjalan cjika bberhasil" dan "itu hanya berjalan cjika adan bkeduanya berhasil" adalah pernyataan yang setara: btidak dapat berhasil kecuali aberhasil.
ruakh

1
@ruakh a || b && clebih ilustratif.
kojiro

8
@ruakh tidak, true || false && echo hiakan ditampilkan hi. Spesifikasi berbunyi, Operator "&&" dan "||" harus memiliki prioritas yang sama dan harus dievaluasi dengan asosiasi kiri.
kojiro

Jawaban:


23

Anda bisa melakukannya seperti ini:

#!/bin/sh
ls -lh &&
    # This is a comment
    echo 'Wicked, it works!'

Saya harap saya mengerti apa yang Anda minta dengan benar.


Terima kasih. Ini adalah yang paling dekat dengan apa yang saya harapkan. Dan itu membuatnya sangat mudah untuk dikonversi kembali menjadi satu liner jika diperlukan.
Mike B

Mike, karena Anda khawatir tentang kebersihan kode, konvensi umum adalah untuk indentasi bagian 2-N dari rantai di bawah yang pertama.
jblaine

@ jblaine Saya tidak yakin saya mengerti maksud Anda. Bisakah Anda jelaskan?
Mike B

Mike, Stackexchange tidak akan membiarkan saya memformat jawaban saya dengan benar, jadi ini yang saya maksud: indent
jblaine

@ jblaine Poin bagus, diedit untuk membuat garis.
Volker Siegel

38

Anda dapat mengubah garis shebang ke

#!/bin/bash -e

Setelah kesalahan, skrip akan berhenti.


1
Menarik. Saya akan mengingatnya. Terima kasih.
Mike B

menyelamatkan saya dari pengetikan set -e saat saya membutuhkannya
Silverrocker

@ Silverrocker Ini juga POSIX (kecuali untuk bashbagian saja). Shell POSIX mengambil banyak opsi yang dapat diterapkan set. Atau sebaliknya? setadalah cara mengatur opsi baris perintah shell dalam skrip.
Kaz

7
Sayangnya, ada sejumlah utilitas standar yang tidak mengikuti konvensi status keluar yang biasa, sehingga -edapat berperilaku tidak benar. Misalnya, Anda mungkin tidak ingin skrip Anda dihentikan setiap kali Anda diffdua file tidak identik. Anda dapat, tentu saja, mengatasi ini dengan menambahkan || true(atau mungkin || [ $? = 1 ]) ke perintah seperti itu, tetapi OP menyebutkan "orang lain" yang harus membaca skrip ini, dan mengatakan "orang lain" mungkin tidak akan terbiasa harus mengatasinya -e.
ruakh

4
Saya biasa meletakkannya -edi she-bang, sampai satu admin perusahaan saya terus meluncurkan skrip saya bash myscript.sh, jadi mengabaikannya -e. Sekarang semua skrip saya ada set -edi baris kedua.
Carlos Campderrós

19

Jika Anda tidak menyukai set -eide itu, mungkin Anda dapat membalikkan logikanya.

foocommand || exit 1
foocommand2 || exit 2
foocommand3 || exit 3

Lebih berguna, ganti exitdengan sesuatu untuk mencetak pesan kesalahan yang berguna, lalu keluar. Dalam fungsi, tentu saja, Anda ingin returnbukan exit.


11
Atau foocommand || exituntuk keluar dengan foocommandstatus keluar jika bukan nol.
Stéphane Chazelas

Bagaimana cara kerjanya? Apakah seperti di C - jika argumen kiri mengevaluasi ke TRUE, tidak ada lagi argumen yang diperiksa?
Vorac

Ya itu betul. Ini adalah ungkapan umum dalam Lisp (dan bahasa fungsional pada umumnya, saya kira) dan dalam Perl.
tripleee

9

Anda dapat menggunakan if else fiblok sebagai gantinya.

if foocommand; then

  # some comments

  if foocommand2; then

    # more comments

    foocommand3
  fi
fi

Ini sedikit lebih mudah dibaca.

Atau Anda bisa menggunakan \untuk membagi 1 liner besar Anda menjadi beberapa baris

foocommand && \
  # some comment
  foocommand2 && \
    # more comment
    foocommand3

Tapi tentu saja ini bisa membingungkan mata yang tidak terlatih.


4
Saya pikir itu \tidak perlu di sana.
Samuel Edwin Ward

Kamu benar. Kekuatan kebiasaan.
Martín Canaval

5

Anda dapat mempertimbangkan untuk menggunakan ifpernyataan bersarang . Pilihan lainnya adalah menggunakan curly's untuk kelompok suka{ true && echo hi; } || echo huh

Pembaruan 1:

Berikut ini contoh tanpa baris baru / komentar:

{ { false && echo "inner true"; } && { echo "inner true" && true; } || { echo "inner false" && false; } || echo "outter false"; }

@Stephane Terima kasih telah menambahkan titik koma. Saya telah menggunakan telepon saya untuk membalas, jadi saya belum memeriksa jawaban saya dua kali. :)
livingstaccato

Ide yang menarik. Ya, saya sudah memikirkan pernyataan bersarang jika tetapi jika saya merantai banyak hal bersama-sama itu bisa berantakan.
Mike B

4

Pisahkan setiap urutan perintah menjadi fungsi:

big_block_1() {
  # ...
}
big_block_2() {
  # ...
}
big_block_3() {
  # ...
}

big_block_1 && big_block_2 && big_block_3

0

Saya selalu suka menulis fungsi "gagal" yang memungkinkan saya menentukan hal yang akan saya lakukan ketika kegagalan terjadi dan kemudian menggunakan ||pola. Seperti yang berikut ini:

function fail() {
  echo "Failure: ${@}"
  exit 1
}

foocommand || fail "couldn't foo"
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.