起動オプションの解析
えーと。何人かの方から指摘されていますが
-sは-dの間違いです。
また、-dのオプションは省略可能なオプションでした。
ということで書式を訂正すると
書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]
です。
それと起動例も
1. cmdopt -o AAA
2. cmdopt -o AAA BBB CCC
3. cmdopt -oq AAA
4. cmdopt -o -q AAA
5. cmdopt -o -d1 AAA
6. cmdopt -o -d 1 AAA
7. cmdopt -q -d2 -o AAA
となります。
フォロー遅くなってしまって申し訳ないです。
期末恒例のお祭りが発生しちゃって^^;;
指摘ありがとうございました。
Posted feedbacks - Flatten
Nested Hiddenちょうど、今日TwitterでBoost.Program_optionsの話題が出てたとこでした。 なんというタイミング。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <iostream>
#include <vector>
#include <string>
#include <exception>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include <boost/program_options/parsers.hpp>
int main(int c, char**v)
{
try {
namespace po = boost::program_options;
int debug;
po::options_description desc("Options");
desc.add_options()
("output,o", "output flag [required]")
("quote,q", "quote flag")
("debug,d", po::value< int >(&debug)->default_value(0), "debug level [0|1|2]")
;
po::options_description hidden("hidden optionis");
hidden.add_options()
("input", po::value< std::vector< std::string > >(), "input file [at least one required]")
;
po::positional_options_description positional;
positional.add("input", -1);
po::options_description visible("Allowed Options");
visible.add(desc);
po::options_description full("Full Options");
full.add(desc).add(hidden);
po::variables_map vm;
po::store(po::command_line_parser(c, v).options(full).positional(positional).run(), vm);
po::notify(vm);
bool error=false;
if ( !vm.count("output") ) {
std::cerr << "*** you must specify -o option\n\n";
error = true;
}
if ( !vm.count("input") ) {
std::cerr << "*** you must specify at least 1 input parameter\n\n";
error = true;
}
if ( debug < 0 || debug > 2 ) {
std::cerr << "*** debug level must be 0, 1 or 2\n\n";
error = true;
}
if ( error ) {
std::cerr << visible << "\n";
return 1;
}
bool output = vm.count("output");
bool quote = vm.count("quote");
if ( output ) {
std::cout << "[オプション情報]\n";
std::cout << "o(output) : " << (output ? "ON" : "OFF") << "\n";
std::cout << "q(quote) : " << (quote ? "ON" : "OFF") << "\n";
std::cout << "d(debug) : " << debug << "\n\n";
std::cout << "[パラメタ情報]\n";
const std::vector<std::string>& input = vm["input"].as< std::vector<std::string> >();
std::cout << "指定数 : " << input.size() << "\n";
for ( int i = 0; i < input.size(); ++i )
std::cout << i+1 << " : " << (quote?"\"":"") << input[i] << (quote?"\"":"") << "\n";
}
return 0;
} catch (const std::exception& e) {
std::cerr << e.what() << "\n";
return -1;
}
}
|
許容例の
-s は、-d の間違いだと思われる。
-d は、省略できないオプションのように思われる。
-d は、必須オプションとして処理しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | use strict;
use Getopt::Std;
#ex>cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 ...]
our( $opt_o, $opt_q, $opt_d );
getopts('oqd:');
die "oオプションが指定されていない\n" unless $opt_o;
die "dオプションが指定されていない\n" unless defined $opt_d;
die "dオプションの引数は0-2\n" unless ($opt_d eq '0' || $opt_d eq '1' || $opt_d eq '2');
die "パラメータが指定されていない\n" unless @ARGV;
print "[オプション情報]\n";
print "o(output): ON\n" if $opt_o;
print "q(quote): " . ($opt_q ? "ON" : "OFF") . "\n";
print "d(debug): $opt_d\n";
print "\n[パラメータ情報]\n";
printf("指定数: %d\n", $#ARGV+1);
my $c = 0;
for my $arg (@ARGV){
$c++;
print "$c: $arg\n";
}
|
いつも使ってる解析ルーチンをベースにしてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #include <stdio.h>
struct cmd_opt{
int opt_o;
int opt_q;
int opt_d;
int string_start;
int string_num;
};
int cmdline(int argc,char* argv[],struct cmd_opt*o){
char* p;
int i=1;
int opt_flag=0;
//必ず-oと文字列が必要
if(argc<3) return -1;
o->opt_o=0;
o->opt_q=0;
o->opt_d=-1;
o->string_start=0;
o->string_num=0;
p=argv[1];
while(i<=argc){
switch(*p){
case '-':
case '+':
case '/':
p++;
opt_flag=1;
break;
default:
break;
}
//オプション解析終了
if(opt_flag==0){
if(o->opt_o==0) return -1;
if(o->opt_d==-1) return -1;
o->string_start=i;
o->string_num=argc-i;
if(o->string_num==0) return -1;
else return 0;
}
switch(*p){
case 'o':
case 'O':
o->opt_o=1;
break;
case 'q':
case 'Q':
o->opt_q=1;
break;
case 'd':
case 'D':
p++;;
if(*p==0){
p=argv[++i];
}
if('0'>*p||*p>'2')
return -1;
o->opt_d=*p-'0';
break;
default:
return -1;
break;
}
p++;
if(*p==0){
p=argv[++i];
opt_flag=0;
}
}
return -1;
}
void put_usage(){
printf("usage:cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 ...]\n");
}
int main(int argc,char* argv[]){
int ret;
int i;
struct cmd_opt o;
ret=cmdline(argc,argv,&o);
if(ret==-1){
put_usage();
return -1;
}
printf("[Option Info]\n");
printf("o(output):%s\n",o.opt_o?"ON":"OFF");
printf("q(output):%s\n",o.opt_q?"ON":"OFF");
printf("d(output):%d\n",o.opt_d);
printf("\n");
printf("[Parameter Info]\n");
printf("String Num:%d\n",o.string_num);
for(i=1;i<=o.string_num;i++){
printf("%d:%s\n",i,argv[i+o.string_start-1]);
}
return 0;
}
|
バッチファイル。遅延環境変数展開で。
お題の起動例にあるパターンはすべて解釈できていると思います。
お題の起動例にあるパターンはすべて解釈できていると思います。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | @echo off
setlocal enabledelayedexpansion
set OPT_O=OFF
set OPT_Q=OFF
set ARGV=
set WAIT_OPT_S=0
shift
for %%1 in (%*) do (
call :parse_arg %%1
)
goto parse_end
rem *** パラメータ解析 ***
:parse_arg
set PARA=%1
if "%PARA:~0,1%"=="-" (
set WAIT_OPT_S=0
call :parse_opt %PARA:~1%
) else (
if "%WAIT_OPT_S%"=="1" set OPT_S=%PARA% & set WAIT_OPT_S=0 & goto :EOF
set ARGV=%ARGV% %PARA%
)
goto :EOF
rem *** オプション解析 ***
:parse_opt
set OPT=%1
:parse_an_opt
if "%OPT%"=="" goto :EOF
set OPT2=%OPT:~0,1%
if "%OPT2%"=="o" (
set OPT_O=ON
) else if "%OPT2%"=="q" (
set OPT_Q=ON
) else if "%OPT2%"=="s" (
set OPT_S=%OPT:~1,1%
set OPT=%OPT:~1%
if "!OPT_S!"=="" set WAIT_OPT_S=1
)
set OPT=%OPT:~1%
goto :parse_an_opt
rem *** 結果出力 ***
:parse_end
echo [オプション情報]
echo o : %OPT_O%
echo q : %OPT_Q%
echo s : %OPT_S%
set /A COUNT=0
for %%1 in (%ARGV%) do set /A COUNT += 1
set /A ARGC=1
echo [パラメータ情報]
echo 指定数:%COUNT%
for %%1 in (%ARGV%) do (
echo !ARGC! : %%1
set /A ARGC += 1
)
endlocal
|
pure bashで内蔵コマンドgetoptsを使いました。
起動例の-sはコマンドじゃなくて引数扱い、と解釈したために、その部分がBKっぽくなっています。
あと、-oは必須ということで、そこの出力は手抜きしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | #!/bin/bash
OPTERR=0
args=()
nargs=0
opt_o=OFF
opt_q=OFF
opt_d=''
while [ $# != 0 ];do
oprind_orig=$OPTIND
while getopts 'oqd:*' opt;do
case "$opt" in
o) opt_o=ON
;;
q) opt_q=ON
;;
d) opt_d=$OPTARG
[[ $opt_d == [012] ]] || exit 1
;;
\?) [[ ! ${!OPTIND} == -* ]] && ((OPTIND--))
break
;;
esac
done
shift $((OPTIND - 1))
OPTIND=1
[ $# != 0 ] && args[$((nargs++))]=$1
shift
done
[ "$opt_o" = OFF ] && exit 1
((nargs)) || exit 1
echo "[オプション情報]
o(output): ON
q(quote): $opt_q
d(debug): $opt_d
[パラメータ情報]
指定数: $nargs"
for ((i = 0; i < nargs; i++));do
echo "$((i + 1)): ${args[$i]}"
done
|
おっと、異常終了とか忘れてた。
バッチファイルの異常終了ってこんなんでいいのかな。
バッチファイルの異常終了ってこんなんでいいのかな。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 46a47,53
>
> set /A COUNT=0
> for %%1 in (%ARGV%) do set /A COUNT += 1
>
> if not "%OPT_O%"=="ON" echo oオプションは必須です。 & exit /b 1
> if "%COUNT%"=="0" echo パラメータは必須です。 & exit /b 1
>
52,54d58
< set /A COUNT=0
< for %%1 in (%ARGV%) do set /A COUNT += 1
<
63a68
> exit /b 0
|
Squeak Smalltalk で、http://ja.doukaku.org/comment/5013/ の方法で得た引数の配列を解析するものを書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | | cmdopt |
cmdopt := [:args |
| output quote debug strings argsStream |
output := false.
quote := false.
debug := 0.
strings := OrderedCollection new.
argsStream := args readStream.
[argsStream atEnd] whileFalse: [
| opt |
opt := argsStream next.
(opt first = $-) ifFalse: [strings add: opt] ifTrue: [
| optStream nextOpt |
optStream := opt allButFirst readStream.
[(nextOpt := optStream next) notNil] whileTrue: [
nextOpt caseOf: {
[$o] -> [output := true].
[$q] -> [quote := true].
[$d] -> [debug := Integer readFrom: (optStream atEnd
ifFalse: [optStream] ifTrue: [argsStream next readStream])]
} otherwise: [^self error: 'unknown option']]]].
output ifFalse: [^self error: 'no output option'].
strings ifEmpty: [^self error: 'no string option'].
{#output->output. #quote->quote. #debug->debug. #strings->strings asArray}].
World findATranscript: nil.
#(
('-o' 'AAA')
('-o' 'AAA' 'BBB' 'CCC')
('-oq' 'AAA')
('-o' '-q' 'AAA')
('-o' '-d1' 'AAA')
('-o' '-d' '1' 'AAA')
('-q' '-d2' '-o' 'AAA')
) do: [:args |
Transcript cr; show: (cmdopt value: args)]
"=>
{#output->true . #quote->false . #debug->0 . #strings->#('AAA')}
{#output->true . #quote->false . #debug->0 . #strings->#('AAA' 'BBB' 'CCC')}
{#output->true . #quote->true . #debug->0 . #strings->#('AAA')}
{#output->true . #quote->true . #debug->0 . #strings->#('AAA')}
{#output->true . #quote->false . #debug->1 . #strings->#('AAA')}
{#output->true . #quote->false . #debug->1 . #strings->#('AAA')}
{#output->true . #quote->true . #debug->2 . #strings->#('AAA')}
"
|
optparse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/usr/bin/env python
# -*- coding: cp932 -*-
from optparse import OptionParser
def main():
usage = u'usage: cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 ...]'
parser = OptionParser(usage)
parser.add_option('-o', '--output', action='store_true')
parser.add_option('-q', '--quote', action='store_true')
parser.add_option('-d', '--debug', type='int',default=0)
(option, args) = parser.parse_args()
if not option.output: parser.error('output option error')
if option.debug not in [0,1,2]: parser.error('debug option error')
if not len(args): parser.error('parameter error')
print u'[オプション情報]'
print u'o(output): ON'
print u'q(quote): %s' % ('ON' if option.quote else 'OFF')
print u'd(debug): %d' % option.debug
print u'\n[パラメーター情報]'
print u'指定数: %d' % len(args)
for i, param in enumerate(args):
print u'%d: %s' % (i+1, param)
if __name__ == "__main__":
main()
|
SRFI-37 や SLIB を使う方法もありますが、とりあえずは gauche.parseopt 版。 -oq のような指定や -d1, -d2 のような指定には対応していないようです。
ところで起動例にある -s オプションは -d ですよね?
;; エラー処理で悩んでしまった。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | (use gauche.parseopt)
(use gauche.sequence)
(define (main args)
(let-args (cdr args)
((output "o|output" #f)
(quiet "q|quiet" #f)
(debug "d|debug=i" 0)
. argv)
(cond
((not output)
(format (current-error-port)
"output option is not supplied.~%"))
((not (memv debug '(0 1 2)))
(format (current-error-port)
"debug option's value must be 0, 1, or 2: ~A~%" debug))
((null? argv)
(format (current-error-port)
"no arguments are supplied.~%"))
(else
(format #t "[options]~%o(output): ON~%q(quote): ~A~%d(debug): ~A~%~%"
(if quiet 'ON 'OFF)
debug)
(format #t "[parameters]~%# of pamameters: ~A~%" (length argv))
(for-each-with-index (lambda (i x) (format #t "~A: ~A~%" (+ i 1) x))
argv)
(exit 0)))
1))
|
args-fold 版。ロングオプション対応。起動例のすべてのパターンを受け付けます(-s を -d にした場合)。
see: SRFI 37
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | (use srfi-37)
(use gauche.sequence)
(define (main args)
(receive (debug output quiet rargv)
(args-fold (cdr args)
(list
(option '(#\d "debug") #t #f
(lambda (option name arg debug output quiet argv)
(values (string->number arg) output quiet argv)))
(option '(#\o "output") #f #f
(lambda (option name arg debug output quiet argv)
(values debug #t quiet argv)))
(option '(#\q "quiet") #f #f
(lambda (option name arg debug output quiet argv)
(values debug output #t argv)))
)
(lambda (option name arg . _)
(error "Unrecognized option: " name))
(lambda (op debug output quiet argv)
(values debug output quiet (cons op argv)))
0 #f #f '())
(cond
((not output)
(format (current-error-port)
"output option is not supplied.~%"))
((not (memv debug '(0 1 2)))
(format (current-error-port)
"debug option's value must be 0, 1, or 2: ~A~%" debug))
((null? rargv)
(format (current-error-port)
"no arguments are supplied.~%"))
(else
(format #t "[options]~%o(output): ON~%q(quiet): ~A~%d(debug): ~A~%~%"
(if quiet 'ON 'OFF)
debug)
(format #t "[parameters]~%# of pamameters: ~A~%" (length rargv))
(for-each-with-index (lambda (i x) (format #t "~A: ~A~%" (+ i 1) x))
(reverse rargv))
(exit 0)))
1))
|
少々無理矢理な感じです。。。Parsecが使えたらもっと楽なのでしょうね(^^;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | data Args = Args {
outputFlag :: Bool,
quoteFlag :: Bool,
debugLevel :: Int,
names :: [String]
} deriving (Show)
newArgs = Args {
outputFlag = False,
quoteFlag = False,
debugLevel = 0,
names = []
}
parse [] result = result
parse (arg:args) result
| arg == "-d" = parse (tail args) result{ debugLevel = read $ head args }
| opt == "-d" = parse args result{ debugLevel = read num }
| (head arg) == '-' = parse args $ parse' (tail arg) result
| otherwise = parse args result{ names = (names result) ++ [arg] }
where
(opt,num) = splitAt 2 arg
parse' [] res = res
parse' ('o':xs) res = parse' xs res{ outputFlag = True }
parse' ('q':xs) res = parse' xs res{ quoteFlag = True }
parse' _ _ = error $ arg ++ " is unknown option."
optParse :: [String] -> Args
optParse args
| (outputFlag result) == False = error "-o is need option."
| (names result) == [] = error "need file name."
| otherwise = result
where
result = parse args newArgs
dump args = do
putStrLn "[Option information]"
putStrLn $ "o(output) : " ++ (onoff $ outputFlag args)
putStrLn $ "q(quote) : " ++ (onoff $ quoteFlag args)
putStrLn $ "d(debug) : " ++ (show $ debugLevel args)
putStrLn ""
putStrLn "[Paramater information]"
putStrLn $ "count : " ++ (show $ length $ names args)
mapM (\(no,name)->putStrLn $ (show no) ++ " : " ++ name) $ zip [1,2..] $ names args
putStrLn ""
where
onoff True = "ON"
onoff _ = "OFF"
main = do
args <- getArgs
dump $ optParse args
{--
mapM_ test testData
mapM_ dumps testData
where
dumps arg = dump $ optParse arg
test arg = putStrLn $ show $ optParse arg
testData = map words ["-o AAA",
"-o AAA BBB CCC",
"-oq AAA",
"-o -q AAA",
"-o -d1 AAA",
"-o -d 1 AAA",
"-q -d2 -o AAA"]
--}
|
えーと。何人かの方から指摘されていますが
-sは-dの間違いです。
また、-dのオプションは省略可能なオプションでした。
ということで書式を訂正すると
書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]
です。
それと起動例も
1. cmdopt -o AAA
2. cmdopt -o AAA BBB CCC
3. cmdopt -oq AAA
4. cmdopt -o -q AAA
5. cmdopt -o -d1 AAA
6. cmdopt -o -d 1 AAA
7. cmdopt -q -d2 -o AAA
となります。
フォロー遅くなってしまって申し訳ないです。
期末恒例のお祭りが発生しちゃって^^;;
指摘ありがとうございました。
とりあえず getopt()を利用したものです。 コンパイラによってはgetopt()が unistd.hにはいっているかもしれません。 僕はいつも起動情報を保持する構造体を作って保持しています。 has~()という関数作ってしまえばあんまり関係ないですけど。。 // gcc -Wall -std=c99 doukaku205.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | #include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
//#include <unistd.h>
#include <getopt.h>
#define OPTION_OUTPUT 'o'
#define OPTION_QUOTE 'q'
#define OPTION_DEBUG 'd'
static char options[] = { ':',
OPTION_OUTPUT
, OPTION_QUOTE
, OPTION_DEBUG, ':'
, '\0' };
struct tagParamInfo
{
bool output;
bool quote;
int debug;
int num;
char *argv0;
char **argv;
} info = { false, false, 0, 0, NULL, NULL};
int main(int argc, char *argv[])
{
int opt;
/* デフォル値 設定 */
/* オプション解析 */
opterr = 0;
while( (opt = getopt(argc, argv, options)) != EOF )
{
switch( opt )
{
case OPTION_OUTPUT:
info.output = true;
break;
case OPTION_QUOTE:
info.quote = true;
break;
case OPTION_DEBUG:
info.debug = strtol(optarg, NULL,10);
if( 0 <= info.debug && info.debug <= 2 )
{
break;
}
case '?':
case ':':
default:
printf("変なオプション[%c]\n", opt);
printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
return 1;
}
}
/* パラメータ設定 */
info.argv0 = argv[0];
info.argv = &argv[optind];
info.num = argc - optind;
if( info.num < 1 )
{
printf("文字列がない\n");
printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
return 1;
}
/* 解析結果の出力 */
printf("[オプション情報]\n");
printf("%-10s:%3s\n", "o(output)", ((info.output==true)?"ON":"OFF"));
printf("%-10s:%3s\n", "q(quote)", ((info.quote==true)?"ON":"OFF"));
printf("%-10s:%3d\n", "d(debug)", info.debug);
printf("\n");
printf("[パラメータ情報]\n");
printf("%-10s:%3d\n", "指定数", info.num);
for( int n=0; n<info.num; n++)
{
printf("%2d:%s\n", n, info.argv[n]);
}
return 0;
}
|
もう一つPOSIX-shのものを投稿 evalって便利ですよね。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #!/usr/bin/sh
OPT_o='OFF'
OPT_q='OFF'
OPT_d='0'
OPTERR=0
while getopts ":oqd:" name
do
case $name in
[oq])
eval "OPT_$name='ON'"
;;
d)
OPT_d=$OPTARG
echo "$OPTARG" | grep -e '[012]' >/dev/null 2>&1
if [ $? -ne 0 ] ; then
echo '変な値: ' "[$OPT_d]"
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
;;
[:?])
echo '変なオプション: ' "[$name]"
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
;;
esac
done
shift $(($OPTIND-1))
if [ $# -eq 0 ]; then
echo '文字列がない'
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
if [ $OPT_o = "OFF" ]; then
echo '-oがない'
echo '書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]'
exit 1
fi
echo '[オプション情報]'
echo 'o(output):' "$OPT_o"
echo 'q(quote):' "$OPT_q"
echo 'd(debug):' "$OPT_d"
echo ''
echo '[パラメータ情報]'
echo '指定数:' "$(($#-1))"
C=0
while [ $C -lt $# ];
do
let C=C+1
echo "$C:$1"
shift
done
#EOF
|
sh版作っていて-oオプションのチェックが抜けていたことに気づくorz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | --- doukaku205.c 2008-09-10 22:23:39.953125000 +0900
+++ doukaku205.c.new 2008-09-10 22:43:58.656250000 +0900
@@ -61,6 +61,14 @@
info.argv0 = argv[0];
info.argv = &argv[optind];
info.num = argc - optind;
+
+ /* 必須チェック */
+ if( info.output != true )
+ {
+ printf("必須オプションがたりない\n");
+ printf("書式:cmdopt -o [-q] [-d{0|1|2}] 文字列 [文字列 ...]\n");
+ return 1;
+ }
if( info.num < 1 )
{
printf("文字列がない\n");
|
#7614の訂正にしたがって簡略化してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | #!/bin/bash
while getopts 'oqd:*' opt;do
case "$opt" in
o) opt_o=ON ;;
q) opt_q=ON ;;
d) opt_d=$OPTARG
[[ $opt_d == [012] ]] || exit 1
;;
esac
done
shift $((OPTIND - 1))
[ -z "$opt_o" ] && exit 1
[ $# = 0 ] && exit 1
echo "[オプション情報]
o(output): ON
q(quote): ${opt_q:-OFF}
d(debug): ${opt_d:-}
[パラメータ情報]
指定数: $#"
i=0
for e in "$@";do
echo "$((++i)): $e"
shift
done
|
OptionParserを使って書いてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | require "optparse"
conf = Hash.new
opts = OptionParser.new
opts.on("-o","--output","set output") { |v| conf[:o] = v }
opts.on("-q","--quote","set quote") { |v| conf[:q] = v }
opts.on("-d DEBUG","--debug=DEBUG",["0","1","2"],"set debug level") { |v| conf[:d] = v }
begin
opts.parse!
if ARGV.size == 0 || !conf.key?(:o)
raise OptionParser::InvalidArgument.new
else
puts "[オプション情報]"
puts "o(output):\t#{conf[:o] ? "ON" : "OFF"}"
puts "q(quote):\t#{(conf[:q] || false) ? "ON" : "OFF"}"
puts "d(debug):\t#{conf[:d] || 0}"
puts ""
puts "[パラメータ情報]"
puts "指定数:\t#{ARGV.size}"
ARGV.zip((1..ARGV.size).to_a) do |a,i|
puts "#{i}:\t#{a}"
end
end
rescue OptionParser::InvalidArgument => ex
puts opts.help
rescue => ex
puts ex.message
end
|




raynstard
#7405()
Rating0/4=0.00
いわゆる、コマンドライン引数の取得(http://ja.doukaku.org/118/)からの派生です。 やっぱ、自分のコマンドってオプションつけたいですよね(笑 タグに「クックブック」なんてつけてみました 長文なのはご容赦ください^^;; ----- 次の起動インタフェースを持つコマンドを作成してください。 書式:cmdopt -o [-q] -d{0|1|2} 文字列 [文字列 ...] 書式を説明すると - オプション「o」 必須オプションです。指定されていない場合、異常終了してください。 - オプション「q」 選択オプションです。 省略されていても問題有りません。 - オプション「d」 引数付きオプションです。 「0」「1」「2」のいずかが続いて指定されます。 - 文字列 パラメータです。 1つ以上であればいくつでも指定できます。 指定されていなかった場合、異常終了してください。 オプションの開始が「-」になっていますが 「+」や「/」でもかまいません。 余力があればロングオプションに対応してもよいです。 起動例:(すべて許容されるのが望ましいです) 1. cmdopt -o AAA 2. cmdopt -o AAA BBB CCC 3. cmdopt -oq AAA 4. cmdopt -o -q AAA 5. cmdopt -o -s1 AAA 6. cmdopt -o -s 1 AAA 7. cmdopt -q -s2 -o AAA 出力例: [オプション情報] o(output): ON|OFF q(quote): ON|OFF d(debug): 0|1|2 [パラメータ情報] 指定数: N 1: 文字列1 2: 文字列2 ... N: 文字列N1 reply [ reply ]