Mengembalikan nilai dari fungsi bash

10

Saya memiliki fungsi yang mengembalikan 1 jika nomor tersebut adalah angka sepuluh digit yang valid:

valNum()
{
    flag=1
    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=0
    fi
    return $flag
}

Itu dipanggil oleh:

if [[ $(valNum $num) -eq 1 ]]; then
      #do something
fi

Fungsi ini berfungsi dengan baik jika nomornya valid tetapi menunjukkan kesalahan sintaksis jika memasukkan nomor yang tidak valid.

pengguna2179293
sumber

Jawaban:

14

@ choroba jawabannya benar, namun contoh ini mungkin lebih jelas:

valNum $num
valNumResult=$? # '$?' is the return value of the previous command
if [[ $valNumResult -eq 1 ]]
then
  : # do something
fi

Contoh ini sedikit lebih lama (pengaturan $valNumResultlalu kueri nilai itu), tetapi lebih eksplisit menggambarkan apa yang terjadi: yang valNum()mengembalikan nilai, dan nilai itu dapat ditanyakan dan diuji.

PS Tolong lakukan sendiri kebaikan dan pengembalian 0untuk truedan bukan-nol untuk false. Dengan begitu Anda dapat menggunakan nilai kembali untuk menunjukkan "mengapa kami gagal" dalam kasus kegagalan.


sumber
8

Fungsi dalam bash hanya dapat mengembalikan kode keluar. Substitusi perintah, sebaliknya, digunakan untuk mendapatkan output standar dari suatu perintah atau fungsi. Karena itu, untuk memeriksa bendera yang dikembalikan, Anda tidak perlu substitusi:

if valNum "$num" ; then
    # ...
fi

Tetapi, agar berfungsi, Anda harus mengembalikan 0 jika nomornya valid, dan 1 jika tidak (kode keluar 0 berarti tidak ada kesalahan).

choroba
sumber
Saya tidak mengerti. Dalam contoh 24.7 di tldp.org/LDP/abs/html/complexfunct.html fungsi mengembalikan nilai maks dan bukan kode keluar. Meskipun saran Anda berfungsi tetapi saya tidak dapat memahami mengapa itu berfungsi
user2179293
1
karena tes Anda adalah untuk mengetahui apakah input bilangan bulat 10-digit yang valid atau tidak, yaitu benar atau salah, fungsi mengembalikan 0 atau 1. contoh choroba berfungsi karena if valnum "$num"sama dengan if valnum "$num" = 0misalnya "jika itu benar". Aturan dasar praktis dalam skrip sh adalah 0 = true / success, non-zero = false / error.
cas
2
BTW, bahwa "Advanced Bash-Scripting Guide" bukanlah panduan yang sangat baik - itu salah tentang banyak hal dan mendorong beberapa praktik scripting yang buruk. Bash FAQ di mywiki.wooledge.org/BashFAQ adalah sumber yang jauh lebih baik.
cas
fungsi Anda gagal karena menggemakan string "Nomor Tidak Valid", dan Anda kemudian melakukan perbandingan numerik antara string itu dan angka 1 denganif [[ $(valNum $num) -eq 1 ]]
cas
5

Anda tidak dapat mengembalikan hasil sewenang-wenang dari fungsi shell. Anda hanya dapat mengembalikan kode status yang merupakan bilangan bulat antara 0 dan 255. (Meskipun Anda dapat meneruskan nilai yang lebih besar ke return, itu terpotong modulo 256.) Nilai harus 0 untuk menunjukkan keberhasilan dan nilai yang berbeda untuk menunjukkan kegagalan; dengan konvensi Anda harus tetap berpegang pada kode kesalahan antara 1 dan 125, karena nilai yang lebih tinggi memiliki makna khusus (perintah eksternal yang buruk untuk 126 dan 127, terbunuh oleh sinyal untuk nilai yang lebih tinggi).

Karena Anda mengembalikan hasil ya-atau-tidak di sini, kode status sesuai. Karena flagtampaknya menunjukkan keberhasilan atau kegagalan, Anda harus menggunakan nilai konvensional 0 untuk sukses dan 1 untuk kegagalan (kebalikan dari apa yang Anda tulis). Anda kemudian dapat menggunakan fungsi Anda secara langsung dalam pernyataan if.

valNum ()
{
  local flag=0
  if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
    echo 1>&2 "Invalid Number"
    flag=1
  fi
  return $flag
}
if valNum "$num"; then
  #do something
fi

Jika Anda perlu membedakan antara kode kegagalan, panggil fungsi secara langsung. Segera setelah itu kembali, kode kegagalan tersedia di $?. Anda kemudian dapat memeriksanya dengan pernyataan kasus:

valNum "$num"
case $? in 

Jika Anda perlu menggunakan kode status nanti, simpan ke variabel lain sebelum $?ditimpa oleh perintah berikutnya.

valNum "$num"
valNum_status=$?

Apa yang Anda tulis tidak berfungsi karena substitusi perintah $(…)meluas ke output fungsi, yang dalam kode Anda adalah pesan kesalahan atau kosong, tidak pernah 1.

Jika Anda perlu memberikan lebih banyak informasi daripada kode status yang memungkinkan dari fungsi shell, Anda memiliki dua kemungkinan:

  • Cetak beberapa teks pada output standar, dan panggil fungsi dalam substitusi perintah: $(valNum "$num")
  • Tetapkan satu atau lebih variabel di dalam fungsi dan baca variabel itu nanti.
Gilles 'SANGAT berhenti menjadi jahat'
sumber
2

Saya sendiri memiliki hasil yang bertentangan di bidang ini. Ini adalah hasil dari eksperimen empiris saya. Pertama, beberapa ' teori ' tentang perintah bash atau * nix:

  • SUKSES == 0 ... yaitu. tidak ada kode status kesalahan)
  • GAGAL! = 0 ...... beberapa kode status

Contoh:

if  ls -lt /nonexistantdir
then 
    echo "found"
else
    echo "FAIL"
fi
#
echo
ls -lt /nonexistantdir; echo "status = $?"
echo "status = $?"

Keluaran:

ls: cannot access '/nonexistantdir': No such file or directory
FAIL... 

ls: cannot access '/nonexistantdir': No such file or directory
status = 2

Seperti yang ditunjukkan, lsperintah mengembalikan kode status = 2. Ketika Anda mencoba direktori yang valid, statusnya nol ( 0 ). Tidak sama dengan hampir semua bahasa lainnya.

aturan # 1 - Buat ...

  • BENAR == 0
  • SALAH! = 0

Kita harus ingat bahwa kita sedang menguji kode kesalahan dalam ifpernyataan Bash . Saya mengatur konstanta, atau Anda dapat menggunakan shell trueatau falseperintah.

TRUE=0
FALSE=1

#  valid number function
#
valNum()
{
    flag=$TRUE

    if [[ $1 != [1-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] ]]; then
        echo "Invalid Number"
        flag=$FALSE
    fi
    return $flag
}

#    later on ...
#
if validNum Abc 
then
    echo "Lucky number"
else
    echo "Not lucky."
fi

dan output:

Invalid Number
Not lucky.

Namun, saya sarankan Anda memberikan @Gilles ' suara-up ' karena jawabannya adalah yang benar. Saya hanya ingin mendapatkan sisi yang simpel pada ePaper.

Hanya satu hal lagi, testperintah. Ini terlihat seperti:

[[ some-expression ]]; 

Sebagian besar waktu. Dan misalnya:

$ test 1
$ echo "result = $?"
result = 0
$ test 0
$ echo "result = $?"
result = 0

Nol (0) benar . Mengapa? Halaman manual mengatakan bahwa satu argumen adalah ' benar ' ketika itu TIDAK-NULL.

referensi:

akan
sumber