Câu hỏi Bash: Cách sử dụng trong khi dịch chuyển; do..case $ 1 trong


Tôi đang làm việc trên một kịch bản bash và tôi cần phải thực hiện "tùy chọn". Làm thế nào tôi có thể làm điều đó với bash?

mục tiêu của tôi là tu chạy script theo cách sau: /myscript.sh -d "/var/log/" -c "test"

những gì tôi đã cố gắng:

while shift; do
        case $1 in
                -d)
                        shift&&DIR="$1"||die
                ;;
                -c)
                        shift&&COMMAND="$1"||die
                ;;
        esac
done

echo "$DIR"
echo "$COMMAND"

4
2018-01-25 14:43


gốc


Và chính xác những gì sẽ xảy ra khi bạn thử điều này? - Dennis
chỉ in trường hợp -c) - teslasimus


Các câu trả lời:


Để mở rộng câu trả lời của @ choroba, đây là một ví dụ về cách sử dụng getopts:

# parse the flag options (and their arguments)
while getopts c:d: OPT; do
    case "$OPT" in
      d)
        DIR="$OPTARG" ;;
      c)
        COMMAND="$OPTARG" ;;
      [?])
        # got invalid option
        echo "Usage: $0 [-d directory] [-c command]" >&2
        exit 1 ;;
    esac
done

# get rid of the just-finished flag arguments
shift $(($OPTIND-1))

Lưu ý rằng sau khi chuyển các đối số cờ, bất kỳ đối số "thông thường" nào sẽ vẫn còn. Vì vậy, tại thời điểm đó, bạn có thể xử lý chúng (ví dụ: ... for arg in "$@"; do ...) hoặc nếu tập lệnh của bạn không lấy chúng chỉ cần cầm nếu bạn nhận được bất kỳ (if [ $# -gt 0 ]; then echo "Usage ...).


5
2018-01-25 15:48



getopt là một phụ thuộc bên ngoài. Tác giả ban đầu chỉ hỏi về sự thay đổi, không phải là getopt. - heroxbd
@heroxbd getopt là một lệnh bên ngoài, nhưng tôi đề xuất getopts (lưu ý "s"), là một nội trang hệ vỏ. - Gordon Davisson


Sai lầm của bạn là bạn đang dịch chuyển ở đầu vòng lặp, quăng đối số đầu tiên trước khi bạn kiểm tra nó. Đây là những gì tôi nghĩ rằng bạn có thể có nghĩa là:

#!/bin/bash
while (( "$#" )); do
   case $1 in
      -d)
         shift&&DIR="$1"||die
         ;;
      -c)
         shift&&COMMAND="$1"||die
         ;;
   esac
   shift
done

echo "$DIR"
echo "$COMMAND"

5
2018-01-25 15:54



chết? bash không phải là Perl - glenn jackman
@glennjackman Bình luận hay. Tôi không hiểu điều đó là một vấn đề có thể xảy ra. (Lưu ý rằng OP giải thích rằng khiếu nại là nó chỉ in các-c) trường hợp.) Tôi giả định die có lẽ là một bí danh - hoặc ít nhất, bất kể điều gì không quan trọng đối với câu hỏi. - Nicole Hamilton
đúng, tôi đã nhận xét nhầm người ... - glenn jackman


Như choroba đã nói, getopts là một cách tiếp cận tốt hơn.

Trong trường hợp của bạn, bạn có thể sử dụng:

getopts c:d: d || die
DIR=$OPTARG
getopts c:d: c || die
COMMAND=$OPTARG

để đạt được những gì bạn đang cố gắng làm với vòng lặp while.

Chuỗi c:d: chỉ định các công tắc có thể. Dấu hai chấm có nghĩa là công tắc yêu cầu đối số.

Vấn đề với cách tiếp cận của bạn là bạn gọi shift trước khi phân tích đối số đầu tiên, loại bỏ nó trong tiến trình.

Để khắc phục điều này, hãy thay đổi vòng lặp while thành những thứ sau:

while true; do
        case $1 in
                -d)
                        shift&&DIR="$1"||die
                ;;
                -c)
                        shift&&COMMAND="$1"||die
                ;;
        esac
        shift || break
done

2
2018-01-25 15:49





Cách tiếp cận thông thường là sử dụng getopts.


1
2018-01-25 15:08