Làm cách nào để thêm phương thức trợ giúp vào tập lệnh shell?


Câu trả lời:


173

đây là một ví dụ cho bash:

usage="$(basename "$0") [-h] [-s n] -- program to calculate the answer to life, the universe and everything

where:
    -h  show this help text
    -s  set the seed value (default: 42)"

seed=42
while getopts ':hs:' option; do
  case "$option" in
    h) echo "$usage"
       exit
       ;;
    s) seed=$OPTARG
       ;;
    :) printf "missing argument for -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
   \?) printf "illegal option: -%s\n" "$OPTARG" >&2
       echo "$usage" >&2
       exit 1
       ;;
  esac
done
shift $((OPTIND - 1))

Để sử dụng điều này bên trong một chức năng:

  • sử dụng "$FUNCNAME"thay vì$(basename "$0")
  • thêm local OPTIND OPTARGtrước khi gọigetopts

1
Tôi đang thử điều này bên trong một chức năng, nhưng khi tôi thử chạy chức năng này, tôi gặp lỗi này "basename: không hợp lệ tùy chọn - 'b'". Có vẻ như nó đang cố gắng vượt qua "-bash" basenamevới dấu gạch đầu dòng.
Morgan Estes

5
Imside một chức năng sử dụng "$FUNCNAME"không "$0". Ngoài ra, thêmlocal OPTIND OPTARG
glenn jackman

Cảm ơn. FUNCNAMElàm. Tôi có tất cả các chức năng của mình trong một tệp duy nhất, vì vậy điều này là hoàn hảo để mở rộng chúng thành một cái gì đó hữu ích cho những người khác.
Morgan Estes

5
@sigur, hãy chắc chắn rằng bạn trích dẫn "$usage" mọi nơi bạn sử dụng nó.
glenn jackman

1
Để làm gì shift $((OPTIND - 1))?
hpaknia

45

Đối số đầu tiên cho tập lệnh shell có sẵn dưới dạng biến $1, vì vậy việc thực hiện đơn giản nhất sẽ là

if [ "$1" == "-h" ]; then
  echo "Usage: `basename $0` [somestuff]"
  exit 0
fi

Nhưng những gì anubhava nói.


Cảm ơn @MarkBooth, đã sửa lỗi chính tả (cộng với cải tiến bằng cách gói dấu ngoặc kép)
seb

Bạn nên tạo thói quen gói if trong [[...]] cho các điều kiện để tránh phân tích cú pháp xấu của một biến, nguồn: github.com/bahamas10/bash-style-guide#bashism
JREAM

2
Có, mặc dù OP không chỉ định bash và [là phiên bản tuân thủ POSIX.
seb

Lưu ý - Để sử dụng bên trong function: Bạn nên thay thế exit 0bằng returnnếu bạn không muốn chấm dứt trình bao sau khi chạy chức năng của mình. (Tôi đã làm điều đó trước)
Đèn chiếu sáng

29

Đây là phần tôi sử dụng để khởi động máy chủ VNC

#!/bin/bash
start() {
echo "Starting vnc server with $resolution on Display $display"
#your execute command here mine is below
#vncserver :$display -geometry $resolution
}

stop() {
echo "Killing vncserver on display $display"
#vncserver -kill :$display
}

#########################
# The command line help #
#########################
display_help() {
    echo "Usage: $0 [option...] {start|stop|restart}" >&2
    echo
    echo "   -r, --resolution           run with the given resolution WxH"
    echo "   -d, --display              Set on which display to host on "
    echo
    # echo some stuff here for the -a or --add-options 
    exit 1
}

################################
# Check if parameters options  #
# are given on the commandline #
################################
while :
do
    case "$1" in
      -r | --resolution)
          if [ $# -ne 0 ]; then
            resolution="$2"   # You may want to check validity of $2
          fi
          shift 2
          ;;
      -h | --help)
          display_help  # Call your function
          exit 0
          ;;
      -d | --display)
          display="$2"
           shift 2
           ;;

      -a | --add-options)
          # do something here call function
          # and write it in your help function display_help()
           shift 2
           ;;

      --) # End of all options
          shift
          break
          ;;
      -*)
          echo "Error: Unknown option: $1" >&2
          ## or call function display_help
          exit 1 
          ;;
      *)  # No more options
          break
          ;;
    esac
done

###################### 
# Check if parameter #
# is set too execute #
######################
case "$1" in
  start)
    start # calling function start()
    ;;
  stop)
    stop # calling function stop()
    ;;
  restart)
    stop  # calling function stop()
    start # calling function start()
    ;;
  *)
#    echo "Usage: $0 {start|stop|restart}" >&2
     display_help

     exit 1
     ;;
esac

Có một điều hơi lạ là tôi đã đặt bắt đầu dừng khởi động lại trong một trường hợp riêng nhưng nó sẽ hoạt động


nếu bạn đưa ra một tùy chọn trống cho -d; nó sẽ không lặp vô hạn?
zerobane

17

Đối với một giải pháp tùy chọn duy nhất nhanh chóng, sử dụng if

Nếu bạn chỉ có một tùy chọn duy nhất để kiểm tra và nó sẽ luôn là tùy chọn đầu tiên ( $1) thì giải pháp đơn giản nhất là ifkiểm tra ( [). Ví dụ:

if [ "$1" == "-h" ] ; then
    echo "Usage: `basename $0` [-h]"
    exit 0
fi

Lưu ý rằng để tương thích posix =sẽ hoạt động tốt như ==.

Tại sao báo giá $1?

Lý do $1cần phải được đặt trong dấu ngoặc kép là nếu không có $1thì shell sẽ cố chạy if [ == "-h" ]và thất bại vì ==chỉ được đưa ra một đối số duy nhất khi nó đang mong đợi hai:

$ [ == "-h" ]
bash: [: ==: unary operator expected

Đối với bất cứ điều gì phức tạp hơn sử dụng getopthoặcgetopts

Theo đề xuất của người khác , nếu bạn có nhiều hơn một tùy chọn đơn giản hoặc cần tùy chọn của mình để chấp nhận một đối số, thì bạn chắc chắn nên sử dụng thêm độ phức tạp getopts.

Là một tài liệu tham khảo nhanh, tôi thích Hướng dẫn getopts 60 giây .

Bạn cũng có thể muốn xem xét getoptchương trình thay vì được tích hợp sẵn getopts. Nó cho phép sử dụng các tùy chọn dài và các tùy chọn sau các đối số không phải tùy chọn (ví dụ foo a b c --verbosethay vì chỉ foo -v a b c). Câu trả lời Stackoverflow này giải thích cách sử dụng GNU getopt.

jeffbyrnes đã đề cập rằng liên kết ban đầu đã chết nhưng rất may cách máy quay lại đã lưu trữ nó.


Cảm ơn! Tôi đã rất vui khi sử dụng getopts trong một năm nay, nhưng tôi cũng sẽ xem xét về getopt.
tttppp

1
Đáng buồn thay, liên kết đến Hướng dẫn getopts 60 giây đã chết; có vẻ như bashcurescancer.com không còn nữa. Đây là một liên kết đến phiên bản của Wayback Machine .
jeffbyrnes


-1

tôi nghĩ bạn có thể sử dụng trường hợp này ...

case $1 in 
 -h) echo $usage ;; 
  h) echo $usage ;;
help) echo $usage ;;
esac
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.