位置パラメータのリストを取得して繰り返し、パラメータのあるフラグとオプションを解析し、解析後にそれらを削除して、デフォルトのパラメータのみを残すスクリプトをどこで見たか覚えていますbash
。その後、スクリプトによって処理されます。case
shift
たとえば、コマンドラインを解析するときは、cp -R file1 -t /mybackup file2 -f
まずパラメータを繰り返し、ユーザーがディレクトリにドロップを要求したかどうかを識別し、ターゲットを指定して-R
強制-t /mybackup
的にコピーし、パラメータリストからそのパラメータを削除してプログラムを次のように-f
残します。file1 file2
処理する残りのパラメーター。
しかし、毎回見るスクリプトを覚えたり、把握できないようです。私はそうすることができるようにしたいです。私は様々なサイトをインターネットで検索し、私が確認した関連ページのリストを添付しました。
サイトの1つの質問は「順序に依存しないオプション」について具体的に質問しましたが、単一の回答や複製された質問に対する回答は、オプションが一般的な引数と混在する上記の状況を考慮しません。この人のために特別な言及理由順番に関係なくオプション。
bash
組み込み関数はオプションではなく最初の引数で停止するようで、getopts
解決策では十分ではないようです。これがWooledge BashFAQページ(以下を参照)でパラメータを並べ替える方法を説明する理由です。しかし、パラメータリストが非常に長い場合は、複数の配列を作成しないでください。
shift
パラメータリストの真ん中で単一のパラメータを表示することはサポートされていないので、私が望むことを達成する簡単な方法が何であるかわかりません。
まったく新しい配列を作成せずにパラメータリストの途中からパラメータを削除できるソリューションがあるかどうかを聞きたいです。
すでに見たページ:
- http://mywiki.wooledge.org/ComplexOptionParsing#Rearranging_arguments
- http://mywiki.wooledge.org/BashFAQ/035
- 長く短いコマンドラインオプションを取得するには、bashシェルスクリプトでgetoptsを使用します。
- http://wiki.bash-hackers.org/scripting/posparams
- http://wiki.bash-hackers.org/howto/getopts_tutorial
- $ @の引数のBashパラメータの例
- Bashスクリプトで順序に依存しないオプションを実装する標準的な方法は何ですか?
- シェルスクリプトでスイッチを処理する方法は?
答え1
POSIXly、オプションの構文解析は、最初の--
非オプション(または非オプションパラメータ)引数の最初のものから停止する必要があります。だから
cp -R file1 -t /mybackup file2 -f
file1
にあるので、cp
すべてfile1
、-t
およびがディレクトリに/mybackup
繰り返しコピーする必要があります。file2
-f
ただし、GNU getopt(3)
(オプションを解析するために使用されます(ここではGNU固有のオプションを使用するためcp
GNUを使用します))は、環境変数が設定されていない限り、引数の後にオプションを受け入れます。したがって、実際にはPOSIXオプションスタイルの解析と同じです。cp
-t
$POSIXLY_CORRECT
cp -R -t /mybackup -f -- file1 file2
getopts
GNUシェル()でも、組み込みシェルはbash
POSIXバージョンのみを処理します。また、長いオプションやオプションのパラメータを持つオプションもサポートされていません。
GNUなどのオプションを解析するには、cp
GNU APIを使用する必要がありますgetopt(3)
。これを行うには、Linuxの場合は次のものを使用できますgetopt
(util-linux
このコマンドgetopt
の拡張バージョンまた、他のUnicesに移植されました。FreeBSD)。
これにより、getopt
オプションが正式に並べ替えられ、ループを介して簡単に解析できますwhile/case
。
$ getopt -n "$0" -o t:Rf -- -Rf file1 -t/mybackup file2
-R -f -t '/mybackup' -- 'file1' 'file2'
通常、次のように使用します。
parsed_options=$(
getopt -n "$0" -o t:Rf -- "$@"
) || exit
eval "set -- $parsed_options"
while [ "$#" -gt 0 ]; do
case $1 in
(-[Rf]) shift;;
(-t) shift 2;;
(--) shift; break;;
(*) exit 1 # should never be reached.
esac
done
echo "Now, the arguments are $*"
また、getopt
GNUと同じ方法でオプションを解析することに注意してくださいcp
。特にGNUと同様に、長いオプションをサポートし(短縮形式で入力)、$POSIXLY_CORRECT
環境変数を尊重します(設定時に引数後のオプションのサポートが無効になります)cp
。
gdbを使用して受信したパラメータを印刷すると、getopt_long()
パラメータを作成するのに役立ちますgetopt(1)
。
(gdb) bt
#0 getopt_long (argc=2, argv=0x7fffffffdae8, options=0x4171a6 "abdfHilLnprst:uvxPRS:T", long_options=0x417c20, opt_index=0x0) at getopt1.c:64
(gdb) set print pretty on
(gdb) p *long_options@40
$10 = {{
name = 0x4171fb "archive",
has_arg = 0,
flag = 0x0,
val = 97
}, {
name = 0x417203 "attributes-only",
[...]
getopt
その後、次のように使用できます。
getopt -n cp -o abdfHilLnprst:uvxPRS:T -l archive... -- "$@"
cp
GNUでサポートされているオプションのリストはバージョンごとに変更される可能性があり、オプションに正当な値を渡すことを確認するgetopt
方法がないことに注意してください。--sparse
答え2
したがって、引数が処理されるたびに処理する必要がある引数リストの次の数字でシェル変数を設定し、ゼロ以外の値を返すことはgetopts
期待しません。値を1に設定する$OPTIND
と、POSIXは新しいパラメーターのリストが許可されることを指定します。したがって、これは単にリターンを観察し、失敗したリターンのインクリメントカウンタプラス記号を保存し、失敗したパラメータを削除し、失敗した各試行をリセットします。ループをカスタマイズするか、変数に保存し、その部分を 。$OPTIND
getopts
getopts
$OPTIND
$OPTIND
opts "$@"
case
eval $case
opts() while getopts :Rt:f opt || {
until command shift "$OPTIND" || return 0
args=$args' "${'"$((a=${a:-0}+$OPTIND))"'}"'
[ -n "${1#"${1#-}"}" ]
do OPTIND=1; done 2>/dev/null; continue
}; do case "$opt" in
R) Rflag=1 ;;
t) tflag=1 ;
targ=$OPTARG ;;
f) fflag=1 ;;
esac; done
$args
実行時に処理されなかったすべての引数に設定されますgetopts
...だから...
set -- -R file1 -t /mybackup file2 -f
args= opts "$@"; eval "set -- $args"
printf %s\\n "$args"
printf %s\\n "$@"
printf %s\\n "$Rflag" "$tflag" "$fflag" "$targ"
出力
"${2}" "${5}"
file1
file2
1
1
1
/mybackup
これは、、、、、bash
...に機能します。まあ、私はその時点で試みを放棄しました。各シェルにも含まれています。重要なのは、処理したくないパラメータのすべての数字が維持されることです。dash
zsh
ksh93
mksh
$[Rtf]flag
$targ
getopts
オプションスタイルを変更しても違いはありません。これは-Rf -t/mybackup
または同様に機能します-R -f -t /mybackup
。リストの中間、リストの終わり、またはリストの先頭で動作します。
それにもかかわらず、最良の方法パラメータリストの最後にforオプションを貼り付け、処理の--
実行shift "$(($OPTIND-1))"
が終わったら実行しますgetopts
。この方法で処理されたすべてのパラメータを削除できます。そしてパラメータリストの終わりを維持します。
私が好きなものの1つは、長期オプションを短期オプションに切り替えることです。私はこれを非常に似た方法で行うので、この答えを簡単に得ることができます。今後私は走るgetopts
。
i=0
until [ "$((i=$i+1))" -gt "$#" ]
do case "$1" in
--Recursive) set -- "$@" "-R" ;;
--file) set -- "$@" "-f" ;;
--target) set -- "$@" "-t" ;;
*) set -- "$@" "$1" ;;
esac; shift; done