Trả về một giá trị từ hàm bash


10

Tôi có một hàm trả về 1 nếu số đó là số có mười chữ số hợp lệ:

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
}

Nó đang được gọi bởi:

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

Hàm hoạt động tốt nếu số hợp lệ nhưng hiển thị lỗi cú pháp nếu nhập số không hợp lệ.

Câu trả lời:


14

Câu trả lời của @ choroba là đúng, tuy nhiên ví dụ này có thể rõ ràng hơn:

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

Ví dụ này dài hơn một chút (thiết lập $valNumResultsau đó truy vấn giá trị đó), nhưng mô tả rõ ràng hơn những gì xảy ra: valNum()trả về một giá trị và giá trị đó có thể được truy vấn và kiểm tra.

PS Hãy làm cho mình một ưu tiên và trả lại 0cho truevà khác không cho false. Bằng cách đó, bạn có thể sử dụng giá trị trả về để cho biết "tại sao chúng tôi thất bại" trong trường hợp thất bại.


8

Các hàm trong bash chỉ có thể trả về mã thoát. Ngược lại, lệnh thay thế được sử dụng để lấy đầu ra tiêu chuẩn của lệnh hoặc hàm. Do đó, để kiểm tra cờ trả về, bạn không cần thay thế:

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

Nhưng, để nó hoạt động, bạn nên trả về 0 nếu số hợp lệ và 1 nếu không (mã thoát 0 có nghĩa là không có lỗi).


Tôi không hiểu Trong ví dụ 24.7 trong tldp.org/LDP/abs/html/complexfunc.html , hàm sẽ trả về giá trị tối đa và không phải mã thoát. Mặc dù đề xuất của bạn đang hoạt động nhưng tôi không thể hiểu tại sao nó lại hoạt động
user2179293

1
vì thử nghiệm của bạn là tìm hiểu xem đầu vào có phải là số nguyên 10 chữ số hợp lệ hay không, tức là đúng hay sai, hàm trả về 0 hoặc 1. ví dụ của choroba hoạt động vì if valnum "$num"tương đương với if valnum "$num" = 0nghĩa là "nếu nó đúng". quy tắc cơ bản của ngón tay cái trong kịch bản sh là 0 = true / thành công, khác không = false / error.
cas

2
BTW, rằng "Hướng dẫn về Bash-Scripting nâng cao" không phải là một hướng dẫn rất tốt - nó sai về rất nhiều điều và khuyến khích một số thực hành kịch bản kém. Câu hỏi thường gặp về Bash tại mywiki.wooledge.org/BashFAQ là tài nguyên tốt hơn nhiều.
cas


chức năng của bạn không thành công vì nó lặp lại chuỗi "Số không hợp lệ" và sau đó bạn thực hiện so sánh số giữa chuỗi đó và số 1 vớiif [[ $(valNum $num) -eq 1 ]]
cas

5

Bạn không thể trả về một kết quả tùy ý từ hàm shell. Bạn chỉ có thể trả về mã trạng thái là số nguyên trong khoảng từ 0 đến 255. (Trong khi bạn có thể chuyển một giá trị lớn hơn return, nó bị cắt bớt modulo 256.) Giá trị phải là 0 để biểu thị thành công và một giá trị khác để biểu thị sự thất bại; theo quy ước, bạn nên giữ mã lỗi trong khoảng từ 1 đến 125, vì các giá trị cao hơn có ý nghĩa đặc biệt (lệnh bên ngoài xấu cho 126 và 127, bị giết bởi tín hiệu cho các giá trị cao hơn).

Vì bạn đang trả về kết quả có hoặc không có ở đây, nên mã trạng thái là phù hợp. Vì flagdường như chỉ ra thành công hay thất bại, bạn nên sử dụng các giá trị thông thường là 0 cho thành công và 1 cho thất bại (ngược lại với những gì bạn đã viết). Sau đó, bạn có thể sử dụng hàm của mình trực tiếp trong câu lệnh 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

Nếu bạn cần phân biệt giữa các mã lỗi, hãy gọi hàm trực tiếp. Ngay sau khi nó trở lại, mã lỗi có sẵn trong $?. Sau đó, bạn có thể kiểm tra nó với một tuyên bố trường hợp:

valNum "$num"
case $? in 

Nếu bạn cần sử dụng mã trạng thái sau, lưu nó vào một biến khác trước khi $?được ghi đè bằng lệnh tiếp theo.

valNum "$num"
valNum_status=$?

Những gì bạn đã viết không hoạt động vì sự thay thế lệnh $(…)mở rộng đến đầu ra của hàm, trong mã của bạn là thông báo lỗi hoặc trống, không bao giờ 1.

Nếu bạn cần truyền nhiều thông tin hơn mã trạng thái cho phép ra khỏi hàm shell, bạn có hai khả năng:

  • In một số văn bản trên đầu ra tiêu chuẩn và gọi hàm thay thế lệnh: $(valNum "$num")
  • Gán cho một hoặc nhiều biến trong hàm và đọc các biến đó sau.

2

Tôi đã có kết quả mâu thuẫn trong lĩnh vực này bản thân mình. Dưới đây là kết quả từ các thí nghiệm thực nghiệm của tôi. Đầu tiên, một số ' lý thuyết ' về các lệnh bash hoặc * nix:

  • THÀNH CÔNG == 0 ... viz. không có mã trạng thái lỗi)
  • FAIL! = 0 ...... một số mã trạng thái

Thí dụ:

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

Đầu ra:

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

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

Như được hiển thị, lslệnh trả về mã trạng thái = 2. Khi bạn thử một thư mục hợp lệ, trạng thái bằng 0 ( 0 ). Không giống như hầu hết các ngôn ngữ khác.

quy tắc số 1 - Thực hiện ...

  • THẬT == 0
  • SAU! = 0

Chúng ta phải nhớ rằng chúng ta đang kiểm tra mã lỗi trong ifcâu lệnh Bash . Tôi thiết lập các hằng, hoặc bạn có thể sử dụng shell truehoặc falsecác lệnh.

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

và đầu ra:

Invalid Number
Not lucky.

Tuy nhiên, tôi khuyên bạn nên đưa ra bất kỳ ' phiếu bầu nào ' @Gilles vì ​​câu trả lời của anh ấy là câu trả lời đúng. Tôi chỉ muốn có được mặt đơn giản xuống trên ePaper.

Chỉ cần một điều khác, testlệnh. Điều này trông giống như:

[[ some-expression ]]; 

Hầu hết thời gian. Và ví dụ:

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

Không (0) là đúng . Tại sao? Vâng, trang người đàn ông nói rằng một đối số duy nhất là ' đúng ' khi nó KHÔNG-NULL.

người giới thiệu:

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.