Tham số tập lệnh trong Bash


103

Tôi đang cố tạo một tập lệnh shell sẽ được sử dụng như thế này:

ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Sau đó, tập lệnh sẽ chuyển đổi tệp hình ảnh thành tệp văn bản. Đây là những gì tôi đã nghĩ ra cho đến nay:

#!/bin/bash
export HOME=/home/kristoffer
/usr/local/bin/abbyyocr9 -rl Swedish -if ???fromvalue??? -of ???tovalue??? 2>&1

Nhưng tôi không biết làm thế nào để lấy các giá trị -from-to. Bất kỳ ý tưởng về cách làm điều đó?


Câu trả lời:


124

Những lập luận rằng bạn cung cấp cho một bashscript sẽ xuất hiện trong các biến $1$2$3có số đề cập đến cuộc tranh cãi. $0là lệnh chính nó.

Các đối số được phân tách bằng dấu cách, vì vậy nếu bạn cung cấp -from-totrong lệnh, chúng cũng sẽ kết thúc bằng các biến này, vì vậy đối với điều này:

./ocrscript.sh -from /home/kristoffer/test.png -to /home/kristoffer/test.txt

Bạn sẽ nhận được:

$0    # ocrscript.sh
$1    # -from
$2    # /home/kristoffer/test.png
$3    # -to
$4    # /home/kristoffer/test.txt

Có thể dễ dàng hơn để bỏ qua -fromvà những -to, như:

ocrscript.sh /home/kristoffer/test.png /home/kristoffer/test.txt

Sau đó, bạn sẽ có:

$1    # /home/kristoffer/test.png
$2    # /home/kristoffer/test.txt

Nhược điểm là bạn sẽ phải cung cấp nó theo đúng thứ tự. Có những thư viện có thể giúp phân tích cú pháp các đối số có tên trên dòng lệnh dễ dàng hơn, nhưng thông thường đối với các tập lệnh shell đơn giản, bạn chỉ nên sử dụng cách dễ dàng, nếu không có vấn đề gì.

Sau đó, bạn có thể làm:

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Các dấu ngoặc kép xung quanh $1$2không phải lúc nào cũng cần thiết nhưng được khuyến khích, bởi vì một số chuỗi sẽ không hoạt động nếu bạn không đặt chúng giữa dấu ngoặc kép.


69

Nếu bạn không hoàn toàn gắn bó với việc sử dụng "from" và "to" làm tên tùy chọn của mình, thì khá dễ dàng để thực hiện điều này bằng cách sử dụng getopts :

while getopts f:t: opts; do
   case ${opts} in
      f) FROM_VAL=${OPTARG} ;;
      t) TO_VAL=${OPTARG} ;;
   esac
done

getopts là một chương trình xử lý các đối số dòng lệnh và phân tích cú pháp chúng thuận tiện cho bạn.

f:t:chỉ định rằng bạn đang mong đợi 2 tham số chứa giá trị (được biểu thị bằng dấu hai chấm). Một cái gì đó như f:t:vnói rằng -vsẽ chỉ được hiểu là một lá cờ.

optslà nơi lưu trữ tham số hiện tại. Các casetuyên bố là nơi bạn sẽ xử lý này.

${OPTARG}chứa giá trị theo sau tham số. ${FROM_VAL}Ví dụ: sẽ nhận được giá trị /home/kristoffer/test.pngnếu bạn chạy tập lệnh của mình như:

ocrscript.sh -f /home/kristoffer/test.png -t /home/kristoffer/test.txt

Như những người khác đang gợi ý, nếu đây là lần đầu tiên bạn viết kịch bản bash, bạn thực sự nên đọc một số điều cơ bản. Đây chỉ là một hướng dẫn nhanh về cách getoptshoạt động.


1
Đây có vẻ là một giải pháp có thể đọc được. Làm thế nào bạn sẽ chỉ định hai cờ sau đó?
Zelphir Kaltstahl

@Zelphir, bạn có thể chỉ định hai hoặc nhiều cờ chỉ cần bỏ qua dấu ":" sau cờ. Ví dụ: f:t:vssẽ là-f some_f -t some_t -v -s
h_s

34

Sử dụng các biến "$1", "$2", "$3"và vân vân để đối số truy cập. Để truy cập tất cả chúng, bạn có thể sử dụng "$@"hoặc để tính số đối số $#(có thể hữu ích khi kiểm tra quá ít hoặc quá nhiều đối số).


24

Tôi cần đảm bảo rằng các tập lệnh của mình hoàn toàn có thể di động giữa các máy khác nhau, shell và thậm chí cả các phiên bản cygwin. Hơn nữa, các đồng nghiệp của tôi, những người mà tôi phải viết kịch bản, là những lập trình viên, vì vậy tôi đã kết thúc sử dụng cái này:

for ((i=1;i<=$#;i++)); 
do

    if [ ${!i} = "-s" ] 
    then ((i++)) 
        var1=${!i};

    elif [ ${!i} = "-log" ];
    then ((i++)) 
        logFile=${!i};  

    elif [ ${!i} = "-x" ];
    then ((i++)) 
        var2=${!i};    

    elif [ ${!i} = "-p" ]; 
    then ((i++)) 
        var3=${!i};

    elif [ ${!i} = "-b" ];
    then ((i++)) 
        var4=${!i};

    elif [ ${!i} = "-l" ];
    then ((i++)) 
        var5=${!i}; 

    elif [ ${!i} = "-a" ];
    then ((i++)) 
        var6=${!i};
    fi

done;

Lý do: Tôi cũng bao gồm một launcher.shtập lệnh, vì toàn bộ hoạt động có một số bước gần như độc lập với nhau (tôi đang nói "quasi", bởi vì mặc dù mỗi tập lệnh có thể chạy riêng, chúng thường chạy cùng nhau ), và sau hai ngày, tôi phát hiện ra rằng khoảng một nửa số đồng nghiệp của tôi, là lập trình viên và tất cả, đều quá giỏi để sử dụng tệp launcher, hãy làm theo "cách sử dụng" hoặc đọc HELP được hiển thị mỗi khi họ làm điều gì đó sai và họ đang tạo ra một mớ hỗn độn, chạy các tập lệnh với các đối số không đúng thứ tự và phàn nàn rằng các tập lệnh không hoạt động bình thường. Tôi là người choleric, tôi quyết định đại tu tất cả các kịch bản của mình để đảm bảo rằng chúng phù hợp với đồng nghiệp. Đoạn mã trên là điều đầu tiên.


2
Tôi thích điều này. Tôi đang thêm một phần vào cuối `else echo" Đối số không hợp lệ: $ {! I} "((i ++))
fi`

6

Trong bash $1là đối số đầu tiên được truyền cho script, $2thứ hai, v.v.

/usr/local/bin/abbyyocr9 -rl Swedish -if "$1" -of "$2" 2>&1

Vì vậy, bạn có thể sử dụng:

./your_script.sh some_source_file.png destination_file.txt

Thuyết minh về dấu ngoặc kép;

xem xét ba tập lệnh:

# foo.sh
bash bar.sh $1

# cat foo2.sh
bash bar.sh "$1"

# bar.sh
echo "1-$1" "2-$2"

Bây giờ gọi:

$ bash foo.sh "a b"
1-a 2-b

$ bash foo2.sh "a b"
1-a b 2-

Khi bạn gọi foo.sh "a b"thì nó sẽ gọi bar.sh a b(hai đối số) và cùng với foo2.sh "a b"nó sẽ gọi bar.sh "a b"(1 đối số). Luôn ghi nhớ cách các tham số được truyền và mở rộng trong bash, nó sẽ giúp bạn đỡ phải đau đầ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.