[关闭]
@natsumi 2015-11-12T02:50:48.000000Z 字数 8206 阅读 1346

[转]Java中的GetOpt

Java


原文:
http://www.thinksaas.cn/group/topic/95851/

在shell工具中,有专门的getopt函数,使用方法如下所示:

  1. while getopts"d:t:vh"opt; do
  2. case"${opt}"in
  3. "d")
  4. DATE="${OPTARG}"
  5. ;;
  6. "t")
  7. ID="${OPTARG}"
  8. ID2=`echo $ID | awk -F"_"'{print $2}'`
  9. ;;
  10. "v")
  11. printVersionInfo
  12. exit 0
  13. ;;
  14. "h")
  15. printHelpInfo
  16. exit 0
  17. ;;
  18. esac
  19. done

其中的”d:t:vh”就是可以接收的选项类型,其中-d和-t意味着可以其后面可以接收参数,而-v和-h后面因为没有:,表示不可以接收参数,只用于单独使用。于是使用这个shell脚本的方式就大概如下:

  1. ./example.sh d d的参数” t t的参数”
  2. ./example.sh h
  3. ./example.sh v

GetOpt在Java1.8的全称为:com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt.GetOpt

Java程序员不能调用sun.*的相关包,以下是oracle给出的原因:
http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html

既然不能够直接调用,就拷贝过来,反正依赖也不多。只需要少许改动,解除与ErrorMsg类的依赖,删除一个MissingOptException(同样改成IllegalArgumentException),就可以直接使用了,以下就是修改后的代码:

  1. /*
  2. * Copyright (c) 2007-2012, Oracle and/or its affiliates. All rights reserved.
  3. * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. /*
  6. * Copyright 2001-2004 The Apache Software Foundation.
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the"License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an"AS IS"BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. /*
  21. * $Id: GetOpt.java,v 1.2.4.1 2005/08/31 11:46:04 pvedula Exp $
  22. */
  23. package util;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import java.util.ListIterator;
  27. /**
  28. * GetOpt is a Java equivalent to the C getopt() library function discussed in
  29. * man page getopt(3C). It provides command line parsing for Java applications.
  30. * It supports the most rules of the command line standard (see man page
  31. * intro(1)) including stacked options such as '-sxm' (which is equivalent to -s
  32. * -x -m); it handles special '--' option that signifies the end of options.
  33. * Additionally this implementation of getopt will check for mandatory arguments
  34. * to options such as in the case of '-d <file>' it will throw a
  35. * MissingOptArgException if the option argument '<file>' is not included on the
  36. * commandline. getopt(3C) does not check for this.
  37. *
  38. * @author G Todd Miller
  39. */
  40. public class GetOpt {
  41. public static final String ILLEGAL_CMDLINE_OPTION_ERR = "ILLEGAL_CMDLINE_OPTION_ERR";
  42. private Option theCurrentOption = null;
  43. private ListIterator<Option> theOptionsIterator;
  44. private List<Option> theOptions = null;
  45. private List<String> theCmdArgs = null;
  46. private OptionMatcher theOptionMatcher = null;
  47. public GetOpt(String[] args, String optString) {
  48. theOptions = new ArrayList<Option>();
  49. int currOptIndex = 0;
  50. theCmdArgs = new ArrayList<String>();
  51. theOptionMatcher = new OptionMatcher(optString);
  52. // fill in the options list
  53. for (int i = 0; i < args.length; i++) {
  54. String token = args[i];
  55. int tokenLength = token.length();
  56. if (token.equals("--")) { // end of opts
  57. currOptIndex = i + 1; // set index of first
  58. // operand
  59. break; // end of options
  60. } else if (token.startsWith("-") && tokenLength == 2) {
  61. // simple option token such as '-s' found
  62. theOptions.add(new Option(token.charAt(1)));
  63. } else if (token.startsWith("-") && tokenLength > 2) {
  64. // stacked options found, such as '-shm'
  65. // iterate thru the tokens after the dash and
  66. // add them to theOptions list
  67. for (int j = 1; j < tokenLength; j++) {
  68. theOptions.add(new Option(token
  69. .charAt(j)));
  70. }
  71. } else if (!token.startsWith("-")) {
  72. // case 1- there are not options stored yet
  73. // therefore
  74. // this must be an command argument, not an
  75. // option argument
  76. if (theOptions.size() == 0) {
  77. currOptIndex = i;
  78. break; // stop processing options
  79. } else {
  80. // case 2-
  81. // there are options stored, check to
  82. // see if
  83. // this arg belong to the last arg
  84. // stored
  85. int indexoflast = 0;
  86. indexoflast = theOptions.size() - 1;
  87. Option op = (Option) theOptions
  88. .get(indexoflast);
  89. char opLetter = op.getArgLetter();
  90. if (!op.hasArg()
  91. && theOptionMatcher
  92. .hasArg(opLetter)) {
  93. op.setArg(token);
  94. } else {
  95. // case 3 -
  96. // the last option stored does
  97. // not take
  98. // an argument, so again, this
  99. // argument
  100. // must be a command argument,
  101. // not
  102. // an option argument
  103. currOptIndex = i;
  104. break; // end of options
  105. }
  106. }
  107. }// end option does not start with"-"
  108. } // end for args loop
  109. // attach an iterator to list of options
  110. theOptionsIterator = theOptions.listIterator();
  111. // options are done, now fill out cmd arg list with remaining
  112. // args
  113. for (int i = currOptIndex; i < args.length; i++) {
  114. String token = args[i];
  115. theCmdArgs.add(token);
  116. }
  117. }
  118. /**
  119. * debugging routine to print out all options collected
  120. */
  121. public void printOptions() {
  122. for (ListIterator<Option> it = theOptions.listIterator(); it
  123. .hasNext();) {
  124. Option opt = (Option) it.next();
  125. System.out.print("OPT =" + opt.getArgLetter());
  126. String arg = opt.getArgument();
  127. if (arg != null) {
  128. System.out.print("" + arg);
  129. }
  130. System.out.println();
  131. }
  132. }
  133. /**
  134. * gets the next option found in the commandline. Distinguishes between
  135. * two bad cases, one case is when an illegal option is found, and then
  136. * other case is when an option takes an argument but no argument was
  137. * found for that option. If the option found was not declared in the
  138. * optString, then an IllegalArgumentException will be thrown (case 1).
  139. * If the next option found has been declared to take an argument, and
  140. * no such argument exists, then a MissingOptArgException is thrown
  141. * (case 2).
  142. *
  143. * @return int - the next option found.
  144. * @throws IllegalArgumentException
  145. * , MissingOptArgException.
  146. */
  147. public int getNextOption() throws IllegalArgumentException {
  148. int retval = -1;
  149. if (theOptionsIterator.hasNext()) {
  150. theCurrentOption = (Option) theOptionsIterator.next();
  151. char c = theCurrentOption.getArgLetter();
  152. boolean shouldHaveArg = theOptionMatcher.hasArg(c);
  153. String arg = theCurrentOption.getArgument();
  154. if (!theOptionMatcher.match(c)) {
  155. // ErrorMsg msg = new
  156. // ErrorMsg(ErrorMsg.ILLEGAL_CMDLINE_OPTION_ERR,
  157. // new Character(c));
  158. throw (new IllegalArgumentException(
  159. String.format("%s : %s",
  160. ILLEGAL_CMDLINE_OPTION_ERR,
  161. new Character(c))));
  162. } else if (shouldHaveArg && (arg == null)) {
  163. throw (new IllegalArgumentException(
  164. String.format("%s : %s",
  165. ILLEGAL_CMDLINE_OPTION_ERR,
  166. new Character(c))));
  167. }
  168. retval = c;
  169. }
  170. return retval;
  171. }
  172. /**
  173. * gets the argument for the current parsed option. For example, in case
  174. * of '-d <file>', if current option parsed is 'd' then getOptionArg()
  175. * would return '<file>'.
  176. *
  177. * @return String - argument for current parsed option.
  178. */
  179. public String getOptionArg() {
  180. String retval = null;
  181. String tmp = theCurrentOption.getArgument();
  182. char c = theCurrentOption.getArgLetter();
  183. if (theOptionMatcher.hasArg(c)) {
  184. retval = tmp;
  185. }
  186. return retval;
  187. }
  188. /**
  189. * gets list of the commandline arguments. For example, in command such
  190. * as 'cmd -s -d file file2 file3 file4' with the usage 'cmd [-s] [-d
  191. * <file>] <file>...', getCmdArgs() would return the list {file2, file3,
  192. * file4}.
  193. *
  194. * @return String[] - list of command arguments that may appear after
  195. * options and option arguments.
  196. * @params none
  197. */
  198. public String[] getCmdArgs() {
  199. String[] retval = new String[theCmdArgs.size()];
  200. int i = 0;
  201. for (ListIterator<String> it = theCmdArgs.listIterator(); it
  202. .hasNext();) {
  203. retval[i++] = (String) it.next();
  204. }
  205. return retval;
  206. }
  207. // /////////////////////////////////////////////////////////
  208. //
  209. // Inner Classes
  210. //
  211. // /////////////////////////////////////////////////////////
  212. // inner class to model an option
  213. class Option {
  214. private char theArgLetter;
  215. private String theArgument = null;
  216. public Option(char argLetter) {
  217. theArgLetter = argLetter;
  218. }
  219. public void setArg(String arg) {
  220. theArgument = arg;
  221. }
  222. public boolean hasArg() {
  223. return (theArgument != null);
  224. }
  225. public char getArgLetter() {
  226. return theArgLetter;
  227. }
  228. public String getArgument() {
  229. return theArgument;
  230. }
  231. } // end class Option
  232. // inner class to query optString for a possible option match,
  233. // and whether or not a given legal option takes an argument.
  234. //
  235. class OptionMatcher {
  236. public OptionMatcher(String optString) {
  237. theOptString = optString;
  238. }
  239. public boolean match(char c) {
  240. boolean retval = false;
  241. if (theOptString.indexOf(c) != -1) {
  242. retval = true;
  243. }
  244. return retval;
  245. }
  246. public boolean hasArg(char c) {
  247. boolean retval = false;
  248. int index = theOptString.indexOf(c) + 1;
  249. if (index == theOptString.length()) {
  250. // reached end of theOptString
  251. retval = false;
  252. } else if (theOptString.charAt(index) == ':') {
  253. retval = true;
  254. }
  255. return retval;
  256. }
  257. private String theOptString = null;
  258. } // end class OptionMatcher
  259. }// end class GetOpt

我们先看GetOpt的构造函数,接收两个参数,第一个就是通过public static void main(String[] args)来指定的,也就是传过来的参数;第二个参数就更加重要了,这个是用来设置可接受选项类型的,这也是与shell中的getopt函数有着相同的含义。

下面就是一段关于getOpt函数的简单使用说明,对于每个选项,不用考虑其出现的顺序,这里也同样接收四种类型选项,其中d,t带具体的附加参数,而v,h没有附加参数,只作为帮助以及版本信息显示使用。

  1. GetOpt getOpt = new GetOpt(args,"d:t:vh");
  2. while ((c = getOpt.getNextOption()) != -1) {
  3. System.out.println((char)c);
  4. switch (c) {
  5. case 'd':
  6. dateString = getOpt.getOptionArg();
  7. break;
  8. case 't':
  9. campaignId = getOpt.getOptionArg();
  10. break;
  11. case 'h' :
  12. printHelpInfo();
  13. break;
  14. case 'v':
  15. printVersionInfo();
  16. break;
  17. }
  18. }

使用getNextOption()函数来逐个获取下一个选项,直到返回-1表示没有下一个参数可以处理。通过switch/case语句对每个选项的附加参数进行区分,并结合getOptionArg()返回该选项中的附件参数,并进行处理。

如果输入了不合法的参数字符,就会抛出以下的错误信息(表明a是未定义的参数字符):

  1. java.lang.IllegalArgumentException: ILLEGAL_CMDLINE_OPTION_ERR : a
  2. at.utils.GetOpt.getNextOption(GetOpt.java:151)

以上就是java中使用getOpt函数的总体介绍,这对于处理linux形式的参数有着非常好的支持,并且符合程序员的习惯。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注