Bash, peringatan tanpa argumen, dan keputusan kasus

110

Saya sedang belajar pesta.

Saya ingin membuat skrip sederhana yang, jika tidak diberikan argumen, menunjukkan beberapa pesan. Dan ketika saya memberikan angka sebagai argumen, tergantung pada nilainya, itu melakukan satu atau lain hal.

Saya juga ingin mengetahui saran untuk manual online terbaik untuk pemula di bash

Terima kasih

Buka jalannya
sumber

Jawaban:

176
if [[ $# -eq 0 ]] ; then
    echo 'some message'
    exit 0
fi

case "$1" in
    1) echo 'you gave 1' ;;
    *) echo 'you gave something else' ;;
esac

The Lanjutan Bash-Scripting Guide cukup bagus. Terlepas dari namanya, itu memperlakukan dasar-dasarnya.

Thomas
sumber
RE: "keluar 0". Saya tidak tahu apakah keluar dari skrip adalah apa yang dia pikirkan. Tapi ya, itu panduan yang sangat bagus.
Trampas Kirk
Saya menafsirkan "dan" sebagai "sebaliknya", dengan asumsi bahwa pesan tersebut akan menjadi teks bantuan. Tapi saya yakin Werner dapat mengetahui apa yang dilakukan baris itu dan apakah dia menginginkannya :)
Thomas
terima kasih, tentu saja! dan terakhir, bagaimana saya bisa mematikan pesan kesalahan ib script, sehingga mereka tidak ditampilkan ke shell?
Buka jalan
Maksud Anda, kesalahan yang keluar dari program tertentu yang Anda panggil? Anda dapat meletakkan > /dev/nulldan / atau 2> /dev/nullsetelah itu untuk mengirim output standar dan / atau aliran kesalahan standar terlupakan.
Thomas
4
Jika Anda menganggap argumen yang hilang sebagai sesuatu yang buruk (seperti skrip kemudian tidak dapat berfungsi dengan baik), kembalikan sesuatu yang berbeda dari 0 ( exit 1). Ada ketentuan lebih lanjut tentang kode pengembalian / keluar, yang dapat Anda temukan secara online dengan cepat, tetapi poin pentingnya adalah bahwa itu tidak boleh 0, yang menunjukkan keberhasilan.
Felix
25

Jika hanya tertarik untuk bailing jika ada argumen tertentu yang hilang, Substitusi Parameter sangat bagus:

#!/bin/bash
# usage-message.sh

: ${1?"Usage: $0 ARGUMENT"}
#  Script exits here if command-line parameter absent,
#+ with following error message.
#    usage-message.sh: 1: Usage: usage-message.sh ARGUMENT
Menepuk
sumber
11

Contoh

 if [ -z "$*" ]; then echo "No args"; fi

Hasil

No args

Detail

-z adalah operator unary karena panjang string adalah nol. $*adalah semua argumen. Tanda kutip untuk keamanan dan merangkum banyak argumen jika ada.

Gunakan man bashdan cari ( / key) untuk "unary" untuk lebih banyak operator seperti ini.

Trampas Kirk
sumber
7
Masalah (minor) dengan ini adalah tidak membedakan antara tidak memberikan argumen dan meneruskan string kosong sebagai argumen. Itu mungkin penting dalam beberapa konteks. Menggunakan [$ # -eq 0] seseorang dapat menangani kedua kasus dengan benar.
Idelic
1
Ah, seluk-beluk pemrograman (ba) sh ... Inilah mengapa aku membencinya.
Thomas
1
anggap -zsebagai mizzing
Ray Foss
4

Tua tapi saya punya alasan untuk mengerjakan ulang jawabannya sekarang berkat beberapa kebingungan sebelumnya:

if [[ $1 == "" ]] #Where "$1" is the positional argument you want to validate 

 then
 echo "something"
 exit 0

fi

Ini akan menggemakan "Sesuatu" jika tidak ada argumen posisi $ 1. Namun, ini tidak memvalidasi bahwa $ 1 berisi informasi spesifik.

Ryan Smith
sumber
$#secara eksplisit adalah jumlah bilangan bulat dari jumlah argumen; itu akan menjadi "0", dan Anda akan menggemakan "sesuatu" meskipun tidak ada argumen, atau itu akan menjadi beberapa bilangan positif, dan Anda akan menggemakan "sesuatu" dengan benar. Tetapi pemeriksaan itu sendiri tidak akan pernah melakukan apa pun, terlepas dari masukan atau kurangnya masukan yang Anda gunakan - pemeriksaan itu akan selalu melaporkan yang $#berisi nilai. Jadi ini sepenuhnya salah dan tidak akan pernah berfungsi seperti yang diklaim.
eschwartz
Apakah Anda benar-benar yakin akan hal itu? Saya memiliki beberapa skrip yang berfungsi sebagaimana mestinya menggunakan format yang tepat ini. Setelah membaca tanggapan Anda, saya bahkan menguji ulang keduanya untuk pertandingan dan kekurangannya. $ # tidak akan berisi nilai jika tidak ditentukan, jika tidak ada argumen posisi yang cocok dengan # apa pun dalam skenario Anda. Tidak masuk akal mengapa bash mengasumsikan nilai dalam argumen posisi yang tidak ada.
Ryan Smith
Coba echo $#sebagai konten skrip /tmp/test.sh, lalu jalankan di bawah / bin / bash serta / bin / sh (atau / bin / dash dan implementasi shell lain apa pun yang Anda miliki. /tmp/test.shAkan echo "0" ke konsol, seperti yang /bin/dash /tmp/test.sh/tmp/test.sh foo/tmp/test.sh first second
diinginkan
Sesuai man bash, di bagian "Parameter Khusus", "Shell memperlakukan beberapa parameter secara khusus. Parameter ini hanya dapat direferensikan; penugasan ke parameter tersebut tidak diperbolehkan.", Dan "# Memperluas ke jumlah parameter posisi dalam desimal." Ini juga diamanatkan oleh POSIX seperti yang dijelaskan di pubs.opengroup.org/onlinepubs/9699919799/utilities/…
eschwartz
Maaf, sepertinya ada miskomunikasi! Maksud saya # sebagai placeholder untuk argumen posisi tertentu (yaitu, $ 2 jika Anda bermaksud argumen kedua) bukan $ # literal. Setelah meninjau Anda di atas, Anda benar-benar benar, $ # literal akan selalu menyelesaikan sejumlah argumen. Maaf atas kebingungannya.
Ryan Smith