- 从命令行输入参数选项是我们基本的程序互动内容,是基本的功能.调用命令行参数是第一个技能,分析命令行参数是第二步.每种不同语言的程序或脚本都具有读取命令行参数的功能.
Python: sys.argv
sys库里的argv是所有命令行选项的列表.根据空格/tab来分隔来放置.第0个是脚本名字,1开始才是参数列表.所以参数个数是len(sys.argv)-1.第一个选项就是sys.argv[1]
python例子
#!/usr/bin/python
# Filename: cat.py
import sys
def readfile(filename):
print '''Print a file to the standard output.'''
f = file(filename)
while True:
line = f.readline()
if len(line) == 0:
break
print line, # notice comma
f.close()
# Script starts from here
# No argv given.
if len(sys.argv) < 2:
print 'No action specified.'
sys.exit()
# Analyse argv with --
if sys.argv[1].startswith('--'):
option = sys.argv[1][2:]
# fetch sys.argv[1] but without the first two characters
if option == 'version':
print 'Version 1.2'
elif option == 'help':
print '''/
This program prints files to the standard output.
Any number of files can be specified.
Options include:
--version : Prints the version number
--help : Display this help'''
else:
print 'Unknown option.'
sys.exit()
else:
for filename in sys.argv[1:]:
readfile(filename)
Shell
shell更为简单,就是调用变量$1 $2 $3
这样子.
$0
脚本文件名$n
n为具体某个数字,指代对于参数.$#
参数总个数.$*
传递给脚本或函数的所有参数。$@
传递给脚本或函数的所有参数。被双引号包含时,"$*"
表示所有参数作为一个整体,"$@"
会表示逐个参数列出来,在for循环时很明显.
Shell例子:
#! /bin/bash
filename=$1
if [ -f ${filename} ];then
echo ${filename}
echo "变量文件名: ${1%.*}"
echo "变量文件所在目录: ${1%/*}"
echo "变量文件的后缀名: ${1##*.}"
fi
C++
主要利用main函数的参数main( int argc, char* argv[] )
.前者指明参数个数,后者是参数数组.
CPP 参数分析器(对象化).
#ifndef OPTPARSER_H
#define OPTPARSER_H
#include <string>
#include <map>
#include <iostream>
using namespace std;
class Option//选项对象,每个选项对象包括简称,全称,是否必须,描述内容.
{
public:
string _shortName; // short name of option
string _longName; // long name of option
string _argRequired; // need an argument?是否需要参数的,0时只是指示器,:需要参数
string _description; // description of option
string _value; // value of option,具体命令行分析后储存递给接口信息
bool _specified; // whether specified in CmdLine,具体命令行分析后用来判断是否指明
public:
Option( const char* shortName = NULL, const char* longName = NULL,
const char* argRequired = NULL, const char* description = NULL )
{
_shortName = shortName ? shortName : "";
_longName = longName ? longName : "";
_argRequired = argRequired ? argRequired : "";
_description = description ? description : "";
_value = "";
_specified = false;
}
};
class OptParser//选项解释器对象,分析和储存程序的选项,并利用接口注册信息
{
public:
OptParser( const int numOpt, const char* options[] );
~OptParser();
bool ParseOpt( int ___argc, char* ___argv[] );//结合具体命令行参数分析.
string GetOpt( const string& opt );//获取存入的命令行参数
bool ExistOpt( const string& opt );//是否有这个参数
void PrintUsage();//打印使用说明
bool NoOptSpecified();//是否非指定性参数.
void ShowOpts( bool all = false );
private://储存了程序内部的选项信息.
int _numOpts; //num of options,多少个预存的选项.
const char** _options; //options,程序预存的选项
string _progname; //program name,所在程序名
map<string, Option*> _optmap; //简称和选项对象,读取命令行参数后存入.
};
#endif
主文件:
#include "OptParser.h"
#include <sstream>
#include <iomanip>
#include <set>
using namespace std;
//// code for test
#ifdef OP_MAIN
int main( int argc, char* argv[] )
{
#ifdef _DEBUG
argc = 6;
argv[0] = "ccbgkit";
argv[1] = "-i=a.mol2";
argv[2] = "-ob.sdf";
argv[3] = "-s";
argv[4] = "3";
argv[5] = "-hv";
#endif
/* step 1.
define all your options in a const char* array
make sure to follow the format, one opt per line.
---------------------------------------------------------------------------
"short_opt", "long_opt", "arg_required", "description",
Note: 1. short_opt starts with -, eg. -i or -out
2. long_opt starts with --, eg. --help or --version
3. arg_required of ":" indicates that opt requires an argument
4. description of opt
---------------------------------------------------------------------------
*/
const char* options[] = {//注册你的选项
"i", "in", ":", "Specify input file",
"o", "out", ":","Specify output file",
"s", "size", ":", "Block size",
"v", "version", 0, "Print version information",
"u", "usage", 0, "Print the usage",
"h", "help", 0, "Print help topic",
"m", "man", 0, "Print the complete man page",
};
/* step 2.
Initialize OptParser with
number of options and the array
*/
OptParser op( 7, options );//注册你的解释器
/* step 3.
Parse the command line
*/
op.ParseOpt( argc, argv );//对输入的命令行的解释
/* step 4.
Get the arg of an option
return "OP::undefined" if opt was undefined in options[];
"OP::unspecified" if opt was unspecified by user;
otherwise the specified arg
*/
string opt_in = op.GetOpt( "in" );//具体情况调用命令行的信息
cout << "CmdLine: ";
for ( int i = 0; i < argc; ++i ) {
cout << argv[i] << " ";
}
cout << "\n";
/*
Show specified options
op.ShowOpts( true ) will show all defined options
*/
op.ShowOpts();
/*
Print (automatically build) formatted usage information
*/
op.PrintUsage();
//
system( "pause" );
exit( 0 );
}
#endif // OP_MAIN
// -------------------------------------------------------------------
OptParser::OptParser( const int numOpts, const char* options[] )
{
//init
_numOpts = numOpts;
_options = options;//备份解析器内信息
for ( int i = 0; i < numOpts; ++i ) {
Option* opt = new Option( options[i*4 + 0], options[i*4 + 1],
options[i*4 + 2], options[i*4 + 3] );//产生选项动态对象的指针
if ( options[i*4 + 0] ) {
_optmap.insert( make_pair( options[i*4 + 0], opt ) );
}
if ( options[i*4 + 1] ) {
_optmap.insert( make_pair( options[i*4 + 1], opt ) );//注册简称和全称对应的选项对象指针的字典.
}
}
}
OptParser::~OptParser()
{
map<string, Option*>::iterator i;//注册个字典的迭代器指针,删除注册信息
set<Option*> cs;//储存选项?
for ( i = _optmap.begin(); i != _optmap.end(); ++i ) {
if ( i->second && cs.find( i->second ) == cs.end() ) {//存在选项.
cs.insert( i->second );
delete i->second;//删除释放内存,回归指针
i->second = NULL;
}
}
_optmap.clear();//清空选项器对象字典的内容
}
bool OptParser::ParseOpt( int ___argc, char* ___argv[] )//将具体命令行用来解释和注册选项器.
{
if ( ___argc == 0 || ___argv == NULL || _optmap.empty() ) {//没输入或预存选项字典为空
cerr << "Something must be wrong\n";
return false;
}
// the program name
_progname = ___argv[0];//注册选项器所在的程序
int optidx = 0;//逐项分析命令行参数,参数索引.
//定义个判断是否参数的宏变量,方便分析.在该索引的参数中, 第一个是不能是-;或 第二个是只有一个字符;或只有两字符而第二个是-
#define IS_ARG ( ___argv[optidx][0] != '-' \
|| ___argv[optidx][1] == '\0' \
|| ( ___argv[optidx][1] == '-' && ___argv[optidx][2] == '\0' ) )
const char* p0( NULL );
const char* p( NULL );
string opt( "" ), val( "" );
/* starts from 1, ARGV[0] is the program name */
for ( optidx = 1; optidx < ___argc; ) {
if ( IS_ARG ) {
//只有当输入 program input.in output.out 这样时调用以下内容
// if ___argc is less than 4 or ___argv[1] and/or ___argv[2]
// are value, make them as default parameters.
// make ___argv[1] as input file and ___argv[2] as output file
if ( optidx == 1 ) {
// if argv[1] is a argument, make it as default input
opt = "in";
if ( _optmap.find( opt ) != _optmap.end() ) {
_optmap[opt]->_specified = true;
_optmap[opt]->_value = ___argv[optidx];
++optidx;
}
else {
cerr << "Croak: no opt can take the parameter '"
<< ___argv[optidx] << "'\n";
return false;
}
continue;
}
if ( optidx == 2 ) {
// if argv[2] is also a argument, make it as default output
opt = "out";
if ( _optmap.find( opt ) != _optmap.end() ) {
_optmap[opt]->_specified = true;
_optmap[opt]->_value = ___argv[optidx];
++optidx;
}
else {
cerr << "Croak: no opt can take the parameter '"
<< ___argv[optidx] << "'\n";
return false;
}
continue;
}
// an argument, unexpected
if ( opt != "" ) {
cerr << "Croak: opt '" << opt
<< "' takes too many arguments\n";
}
else {
cerr << "Croak: no opt can take the parameter '"
<< ___argv[optidx] << "'\n";
}
return false;
}
else {
// an option
p0 = ___argv[optidx] + 1 + ( ___argv[optidx][1] == '-' );//参数内容,根据-或--定义参数内容指针
for ( p = p0; *p && *p != '='; ++p ) {//非结尾或=时,将p移到参数如--sin=hi的sin的=处
/* do nothing */
}
opt.assign( p0, p - p0 );//sin选项名,p0起p-p0个字符
/* Test all options for exact match match */
if ( _optmap.find( opt ) != _optmap.end() ) {
if ( *p ) {//到达的非结尾,只有=情况罗
// *p == '='
if ( _optmap[opt]->_argRequired == ":" ) {//是要赋值的选项
// ok, expects an arg
val.assign( p + 1 );//将选项的值放入val
//
_optmap[opt]->_specified = true;//已指定
_optmap[opt]->_value = val;//给该选项放置值.
// advance to next ARGV-element
optidx++;//完成读取一个选项,下一个选项继续.
continue;
}
else {//非赋值型选项给了值,如-s=hi,但-s只是只是选项
// error, opt expects no argument
cerr << "Croak: opt '" << opt
<< "' expects no argument!\n";
return false;
}
}
else {//到达的是结尾,例如-s,--sin.而-oFile.out则因为没有该选项.
//
++optidx;//读取下一选项,这才是值
if ( optidx >= ___argc ) {
// the last ARGV-element
if ( _optmap[opt]->_argRequired == "" ) {//非赋参选项.
// ok, expects no arg
_optmap[opt]->_specified = true;
return true;
}
else {
// error, expects an arg
cerr << "Croak: opt '" << opt
<< "' expects an argument!\n";
return false;
}
}
if ( IS_ARG ) {//如下一选项是一个参数值,例如-f file的file
if ( _optmap[opt]->_argRequired == ":" ) {
// ok, expects an arg
val.assign( ___argv[optidx] );//好,是一个值,给该参数赋值
//
_optmap[opt]->_specified = true;
_optmap[opt]->_value = val;
// advance to next ARGV-element
++optidx;
continue;
}
else {
// error, expects no arg,不该赋值的赋值了报错
cerr << "Croak: opt '" << opt
<< "' expects no argument!\n";
return false;
}
}
else {//是不给参数型的选项
// an opt
if ( _optmap[opt]->_argRequired == "" ) {
// ok, expects no arg
_optmap[opt]->_specified = true;
}
else {
// error, expects an arg
cerr << "Croak: opt '" << opt
<< "' expects an argument!\n";
return false;
}
}
}
}
/* otherwise interpret as bundled short opt */
else {//找不到这个词作为参数,例如-oFile.out型参数,复合参数-sk或-K没有该参数.
for ( p = p0; *p; ++p ) {//重新分析该选项
opt.assign( p, 1 );//-oFile的o
if ( _optmap.find( opt ) != _optmap.end() ) {
if ( _optmap[opt]->_argRequired == ":" ) {
// expects an argument, accept all the rest
val.assign( p + 1 );//-oFile.out将后面都当做值
//
_optmap[opt]->_specified = true;
_optmap[opt]->_value = val;
// break out
break;//跳出不再读了.
}
else {//-sk型的符合选项
_optmap[opt]->_specified = true;
continue;
}
}
else {//-sK没定义的K
// not defined
cerr
<< "Croak: opt '"
<< opt
<< "' is not defined!\n";
return false;
}
}
// advance to next ARGV-element
++optidx;
continue;
}
}
}
//
return true;
}
string OptParser::GetOpt( const string& opt )
{
if ( _optmap.find( opt ) != _optmap.end() ) {
if ( _optmap[opt]->_specified ) {
return _optmap[opt]->_value;
}
else {
return "OP::unspecified";//未赋值,未提供
}
}
else {
return "OP::undefined";//未定义
}
}
bool OptParser::ExistOpt( const string& opt ) {
if ( _optmap.find( opt ) != _optmap.end() ) {//有定义时,赋值了或未
return _optmap[opt]->_specified;
}
return false;//压根没定义
}
void OptParser::PrintUsage()
{
map<string, Option*>::const_iterator i;
string usage, shortopt, bundled;
stringstream detail;
// max short name size and long name size,为了输出时对齐...
int maxSNSize = 0;
int maxLNSize = 0;
for ( i = _optmap.begin(); i != _optmap.end(); ++i ) {
int snsize = (int)(i->second->_shortName).size();
int lnsize = (int)(i->second->_longName).size();
if ( snsize > maxSNSize ) {
maxSNSize = snsize;
}
if ( lnsize > maxLNSize ) {
maxLNSize = lnsize;
}
}
usage += " Usage: " + _progname;
for ( int N = 0; N < _numOpts; ++N ) {
for ( i = _optmap.begin(); i != _optmap.end(); ++i ) {
if ( i->first == _options[N*4 + 0] &&
i->first == i->second->_shortName ) {
if ( i->second->_argRequired != "" ) {
usage += " [-" + i->first + " <:>]";
}
else if ( ( int ) i->first.size() > 1 ) {
shortopt += " [-" + i->first + "]";
}
else {
bundled += i->first;
}
detail << " -" << left
<< setw( maxSNSize + 1 ) << i->first
<< left << setw( maxLNSize + 5 )
<< ( i->second->_longName != ""
? " --" + i->second->_longName
: " " )
<< left << i->second->_description << "\n";
break;
}
}
}
cout << usage << shortopt << " [-" << bundled << "]" << "\n\n";
cout << detail.str() << "\n";//将字符串流中变字符串并输出.
}
bool OptParser::NoOptSpecified() {
map<string, Option*>::const_iterator i;
for ( i = _optmap.begin(); i != _optmap.end(); ++i ) {
if ( i->second->_specified ) {
return false;
}
}
return true;
}
void OptParser::ShowOpts( bool all )
{
map<string, Option*>::const_iterator i;
for ( i = _optmap.begin(); i != _optmap.end(); ++i ) {
if ( i->first == i->second->_shortName
&& ( all || i->second->_specified ) ) {
cout << "opt '" << i->first << "' " << i->second->_value << endl;
}
}
}
Fortran
argc=iargc()
命令行参数个数,用于方便循环读取.
call getarg(i,buffer)
读取命令行,i是第几个,buffer是字符组用于储存.
Fortran例子
分析参数, 将多个输入参数的磨光次数进行排序. 更多细节和后续用法就不列了.
!* For input arguments
!* 1st: file; other: polish times for writing result.
argc=iargc();
CALL GETARG(1, mapname)
if (argc < 1) then
print *,'Error, Please assign the filename!'
print *,'1:filename '
stop
end if
! Analyse file name.
dotPlace=index(mapname,'.',back = .true.);
basename=mapname(:dotPlace-1);
extname=mapname(dotPlace+1:);
if (extname(1:3)/='map') then
print *,'Error, Please assign the filename!'
print *,'1:filename '
stop
endif
! read the other arguments
Kpolish=0; j=0
if (argc>1) then
do i=2,argc
call GETARG(i,tmpstr)
read(tmpstr,*) j
if (j == 0 ) then
readFromMap=.true.
writedat=.false.
else
Kpolish=Kpolish+1
Tpolish(Kpolish)=j
end if
enddo
!* sort from small to large
call bubble_sort(Tpolish,Kpolish);
else
readFromMap=.true.
endif