getoptsパラメータを他の入力と一緒に使用できますか?

getoptsパラメータを他の入力と一緒に使用できますか?

文字列を入力として使用し、ユーザーがパラメーターをインジケーターとして選択できる他のオプションを使用するスクリプトを作成しています。つまり、これは次のようになります。

./script "My input string" -pxz

または

./script -pxz "My input string"

しかし、次の問題に直面しました。 getoptsコマンドがgetopts以外のスタイル引数を入力した後、動作が停止したようです。たとえば、次のようになります。

#!/bin/bash

while getopts "ab" arg; do
    echo $arg received
done

実行すると、次のようになります。

$ ./example.sh -a -b -a string -b
a received
b received
a received
$

「文字列」で止まり続けません。 getopts コマンドは、"string" が読み取ると予想される引数型ではないため、ゼロ以外の終了状態を返し、while ループが終了します。 2番目のものを追加しようとしましたが、while getopts何の効果もありませんでした。 getoptsの「読み取りヘッド」は依然として対応する「文字列」パラメータに固定されており、ゼロ以外の終了状態で再び終了します。

これは、getoptsが文字列を読み取ってそこに到達できないため、ユーザーが最初に文字列を入力してからオプションを入力することを許可しないことを意味します。だから私はこれを行うことはできません:

./script "My input string" -pxz

一方、ユーザーに最初にオプションを入力してから文字列を入力するように求めると、文字列の検索方法に問題が発生します。通常、選択の余地がない場合は、次のようにします。

string="$1"

しかし、今はオプションがあり、どのくらいのかわからないので、文字列がどの場所を占めているのかはもうわかりません。では、どうやって戻すことができますか?

これで理想的には、私のスクリプトは実際には双方向で動作することができるか、2つの組み合わせで動作できるはずです。次の入力を処理できる必要があります。

./script -p "My input string" -xz

それでは、この問題をどのように解決するのですか?

ベストアンサー1

getoptLinuxを使用していてutil-linux(またはBusybox)のコマンドがある場合は、GNUツールのように引数の順序を変更することもできます。また、引数、オプション引数、オプションのオプション引数、および終了オプションの処理--でスペースをサポートします。

標準動作は、最初の非オプションが見つかった場合はオプションの処理を停止することであるため、他の実装では混合オプションと非オプションをサポートしていない可能性があります。設定すると、POSIXLY_CORRECTGNUでもサポートされません。

とにかく、次のスクリプトを使用してください。

$ ./opts.sh -a 123 "arg with space" more -bc args -- -also -args
option -a with arg '123'
option -b
option -c
remaining arguments (5):
<arg with space> <more> <args> <-also> <-args> 

opts.sh:

#!/bin/bash

getopt -T
if [ "$?" -ne 4 ]; then
    echo "wrong version of 'getopt' installed, exiting..." >&2
    exit 1
fi 
params="$(getopt -o a:bc -- "$@")"
eval set -- "$params"
while [ "$#" -gt 0 ]; do
    case "$1" in
    -a)
        echo "option -a with arg '$2'"
        shift 2;;
    -b)
        echo "option -b"
        shift;;
    -c)
        echo "option -c"
        shift;;
    --) 
        shift
        break;;
     *) 
        echo "something else: '$1'"
        shift;;
    esac
done
echo "remaining arguments ($#):"
printf "<%s> " "$@"
echo

(上記のスクリプトはgetoptutil-linuxの改善と互換性のある実装でのみ機能することに注意してください。他の「レガシー」実装にはパラメータなどの空白の問題があります。このgetopt -Tテストは実装が互換性があることを確認するために使用されます。)

おすすめ記事