Câu hỏi Tham số tập lệnh trong Bash


Tôi đang cố gắng thực hiện một kịch bản shell mà nên đượ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 đã đưa 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 để có được -from và -to giá trị. Bất kỳ ý tưởng về cách làm điều đó?


76
2017-08-01 19:57


gốc


bạn nên đọc tldp.org/LDP/Bash-Beginners-Guide/html/… - Mehul Rathod
Đây là một bài viết tốt hơn về chủ đề này: Làm cách nào để phân tích cú pháp đối số dòng lệnh trong bash? - Igor Fobia


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


Các đối số mà bạn cung cấp cho bashscript sẽ xuất hiện trong các biến $1 và $2 và $3 trong đó số tham chiếu đến đối số. $0 chính là lệnh.

Các đối số được phân cách bằng dấu cách, vì vậy nếu bạn cung cấp -from và -to trong lệnh, chúng sẽ kết thúc trong các biến này, vì vậy cho đ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

Nó có thể dễ dàng hơn để bỏ qua -from và -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 thứ tự đúng. Có những thư viện có thể làm cho việc phân tích cú pháp các đối số được đặt tên trên dòng lệnh dễ dàng hơn, nhưng thường đối với các kịch bản lệnh đơn giản, bạn chỉ nên sử dụng một 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

Dấu ngoặc kép xung quanh $1 và $2 khô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.


90
2017-08-01 20:09





Nếu bạn không hoàn toàn gắn liền với việc sử dụng "từ" và "đến" làm tên tùy chọn của mình, việc thực hiện điều này khá dễ 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 chúng một cách thuận tiện cho bạn.

f:t: xác đị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). Cái gì đó như f:t:v nói rằng -v sẽ chỉ được hiểu là cờ.

opts là nơi thông số hiện tại được lưu trữ. Các case tuyên bố là nơi bạn sẽ xử lý điều này.

${OPTARG} chứa giá trị sau tham số. ${FROM_VAL} ví dụ sẽ nhận được giá trị /home/kristoffer/test.png nế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 đề xuất, 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ố vấn đề cơ bản. Đây chỉ là một hướng dẫn nhanh về cách getopts công trinh.


55
2017-08-01 20:17



Điều nà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
@Zelphir, bạn có thể chỉ định hai hoặc nhiều cờ chỉ đơn giản là ommiting ":" sau cờ. Ví dụ f:t:vs sẽ là -f some_f -t some_t -v -s - h_s


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


25
2017-08-01 20:13





Tôi cần đảm bảo rằng các tập lệnh của mình hoàn toàn di động giữa các máy, vỏ 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 là những người tôi phải viết kịch bản, là lập trình viên, vì vậy tôi đã sử dụng điều 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 đưa vào launcher.sh kịch bản là tốt, vì toàn bộ hoạt động có một số bước độc lập với nhau (tôi nói "quasi", bởi vì mặc dù mỗi tập lệnh có thể tự chạy, nhưng chúng thường chạy cùng nhau) và trong hai những 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ả, quá tốt để sử dụng tệp khởi chạy, 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 thực hiện một mớ hỗn độn của toàn bộ điều, chạy kịch bản với các đối số theo thứ tự sai và phàn nàn rằng các tập lệnh không hoạt động đúng. Là kẻ ăn năn Tôi quyết định sửa chữa tất cả các kịch bản của mình để đảm bảo rằng chúng là đồng nghiệp. Đoạn mã trên là điều đầu tiên.


15
2017-07-06 14:55



Tôi thích điều này. Tôi đang thêm một phần ở cuối `else echo" Đối số không hợp lệ: $ {! I} "((i ++)) fi` - CJBS
tôi thích giải pháp này. dễ đọc và dễ sử dụng. - Christian Noel


Trong bash $1 là đối số đầu tiên được truyền cho tập lệnh, $2 thứ hai và như vậy

/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

Giải thích 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" sau đó nó gọi bar.sh a b (hai đối số), và với foo2.sh "a b" nó gọi bar.sh "a b" (1 đối số). Luôn luôn có trong tâm trí như thế nào các thông số được thông qua và mở rộng trong bash, nó sẽ giúp bạn tiết kiệm rất nhiều đau đầu.


6
2017-08-01 20:02



Đáng yêu! Cảm ơn bạn!! - Kristoffer