您尚未登录。

#1 2013-10-04 20:07:34

careone
会员
注册时间: 2013-10-04
帖子: 9

求助:bash中如何提取命令行选项的辅助参数

求助:bash中如何提取命令行选项的辅助参数

主程序名称: emacs-locale

程序目标:
* 判断并提取 -gl, -l -v 这三个选项的辅助参数,并保存到三个对应的数组中。
  数组定义为 ARRAY_GL, ARRAY_L, ARRAY_V   

示例如下:
   

./emacs-locale -gl zh_CN -v 24.3

   

./emacs-locale -l zh_CN -v 24.3

    说明:
    -gl 代表全局语言相关选项(Global Language);
     -l 代表当前用户语言相关选项(Language);
     -v 代表 Emacs 版本号 (Version);

* 容错功能

  ** 每个选项后允许输入多个参数,如:

   

./emacs-locale -gl zh_CN -v 24.3 23.1

   

./emacs-locale -gl zh_CN zh_TW -v 24.3 23.1

  ** 如果同一选项提供多次输入,则合并有效参数,如:
   

./emacs-locale -gl zh_CN -v 24.3 23.1 -gl zh_TW

    等效于:
   

./emacs-locale -gl zh_CN zh_TW -v 24.3 23.1

   

  ** 能自动过滤无辅助参数的无效选项,如
   

./emacs-locale -gl -gl zh_CN -v 24.3 23.1 -gl zh_TW

    上面的 -gl 选项出现多次,需要过滤

* 说明
    完整的程序还有更多功能,这里仅列待解决部分的代码

相关代码见2楼

调试时发现有时能正确提取参数,但有时出现异常.
运行环境:
Ubuntu 10.04.3 i386
GNU bash, version 4.1.5(1)-release

示例代码如下:
命令行

./emacs-locale -gl gl1 gl2 gl3 -v v10 v11 -l l1 l2 -l l2 -l l3  -gl gl2 -v v21 gl

输出如下(输出结果有误,-l 选项的参数未能正确提取)

----
ARRAY_GL = 'gl1 gl2 gl3'
ARRAY_L = ''
ARRAY_V = 'v10 v11'

有劳哪位高手指点一下,多谢!

离线

#2 2013-10-04 20:08:11

careone
会员
注册时间: 2013-10-04
帖子: 9

Re: 求助:bash中如何提取命令行选项的辅助参数

接 1 楼
程序代码

#! /bin/bash
## coding: utf-8
## translate Emacs/XEmacs menu to other languages
## updated by Careone <emacslocale@126.com>, 2013-10-04

VERSION='2.12' 

# Usage: usage
# Print the usage.
usage () {
    cat <<EOF
Usage: $0 [OPTION]
toggle $NAMEU menu to special language, for current user or global.
  You also can translate $NAMEU menu to special language(s) if translate 
scripts existed. Please run '$0 -d' for translate/develop options.

  -V, --version    print the version information and exit
  -h, --help       print this message and exit

Translate and develop related options
usage:    $0 -l LANGUAGE -v VERSION
examples: $0 -l zh_CN -v 24.1
          $0 -l zh_CN -v 24.1 24.2
          $0 -l zh_CN zh_TW -v 24.1 24.2

      -gl [LANGUAGE_1 LANGUAGE_2 ...]    (root please!)
        with -v, (Global) translate $NAMEU lisp/*/*.el files to special 
        version(s). If no VERSION given, try probe current $NAMEU version
        installed instead.
      -l [LANGUAGE_1 LANGUAGE_2 ...]
        with -v, translate $NAMEU lisp/*/*.el files to special language(s)
      -v [VERSION1 VERSION2 ...]
        with -gl or -l, translate $NAMEU lisp/*/*.el files to special version(s). If
        no VERSION given, try probe current $NAMEU version installed instead.

      !!! NOTICE !!!
       * option '-l':
         translated .el files save to ~/$TRANSOF/usr/share/$NAMEL/... and
         apply to current user only

       * option '-gl': (root please!)
         translated .el files save to /usr/share/$NAMEL/... and apply to ALL
         USERS. If you just want to test your translations, please use option 
         '-l' instead!
	
EOF
}
###

# tag 2000
## PART 2: main
# Check the arguments.

for option in "$@"; do
    case "$option" in
    -h | --help)
	usage
	exit 0 ;;

## todo -------------------------
    -gl | -l | -v)
    declare -a ARRAY_GL
    declare -a ARRAY_L
    declare -a ARRAY_V
    declare -a ARG

## 2013-09-20
#ARGS="$@"
  case "$1" in
  -gl)
    	shift
	unset ARG[@] #init array to null
	ARG=( `echo -n "$@" | sed "s/ -/\n -/" | head -1` )

  if [ "${#ARG[@]}" -ge 1 ];then 
	# if argument like "-gl -gl zh_CN", throw the first -gl
	case "${ARG[0]}" in
	--* | -*): ;; 
	*)

	  if [ "${#ARRAY_GL[@]}" -ge 1 ];then 
	    ARRAY_GL=( "${ARRAY_GL[@]}" "${ARG[@]}" )
	  else ARRAY_GL=( "${ARG[@]}" )
	  fi
	  shift "${#ARG[@]}"	
#	echo "ARRAY_GL = '${ARRAY_GL[@]}'"
	esac
  fi  
 	continue
	;;

  -l)
    	shift
	unset ARG[@] #init array to null
	ARG=`echo -n "$@" | sed "s/ -/\n -/" | head -1`

  if [ "${#ARG[@]}" -ge 1 ];then 
	# if argument like "-l -l zh_CN", throw the first -l
	case "${ARG[0]}" in
	--* | -*): ;; 
	*)

	if [ "${#ARG[@]}" -ge 1 ];then 
  	  if [ "${#ARRAY_L[@]}" -ge 1 ];then 
	    ARRAY_L=( "${ARRAY_L[@]}" "${ARG[@]}" )
	  else ARRAY_L=( "${ARG[@]}" )
	  fi
	  shift "${#ARG[@]}"	
	fi
#	echo "ARRAY_L = '${ARRAY_L[@]}'"
	esac
  fi  
 	continue
	;;
  -v)
    	shift
	unset ARG[@] #init array to null
	ARG=`echo -n "$@" | sed "s/ -/\n -/" | head -1`
	
  if [ "${#ARG[@]}" -ge 1 ];then 
	# if argument like "-v -v 24", throw the first -v
	case "${ARG[0]}" in
	--* | -*): ;; 
	*)

	if [ "${#ARG[@]}" -ge 1 ];then 
	  if [ "${#ARRAY_V[@]}" -ge 1 ];then 
	    ARRAY_V=( "${ARRAY_V[@]}" "${ARG[@]}" )
	  else ARRAY_V=( "${ARG[@]}" )
	  fi
	  shift "${#ARG[@]}"	
	fi
#	echo "ARRAY_V = '${ARRAY_V[@]}'"
	esac
  fi  
 	continue
 	;;
  -*):
	shift; continue
	 ;;
  esac
# Case of "-gl | -l | -v)" end
	;; 
##--------------------------
    -*)
	echo "Unrecognized option \`$option'" 1>&2
	#exit 1
	;;
    esac

done

# ,FUZZY
##--------------------------
	echo
	echo "----"
	echo "ARRAY_GL = '${ARRAY_GL[@]}'"
	echo "ARRAY_L = '${ARRAY_L[@]}'"
	echo "ARRAY_V = '${ARRAY_V[@]}'"
exit 0;

#
# -gl gl1 gl2 gl3 -v v10 v11 -l l1 l2 -l l2 -l l3  -gl gl2 -v v21 gl
### output:
#----
# ARRAY_GL = 'gl1 gl2 gl3'
# ARRAY_L = ''
# ARRAY_V = 'v10 v11'

离线

#3 2015-09-15 03:52:55

Arthur2e5
Overuse the Shell!
注册时间: 2015-09-15
帖子: 4
个人网站

Re: 求助:bash中如何提取命令行选项的辅助参数

真悲伤,用这种坑爹语法害我不能飞 getopts 内置……还真得踩着你的 for 走呢。

# tag 2000
## PART 2: main
# Check the arguments.

# 匈牙利命名法吃 * 啦。
ARRAY_GL=()
ARRAY_L=()
ARRAY_V=()
BUF=()

# misaka-pseudo:
#   each ARG:
#     -gl <list> => ARRAY_GL.append(list)
#     -v <list> => ARRAY_V.append(list)
#     -l <list> => ARRAY_L.append(list)
# list can be nil, but none of its elements may contain any of the opts above.
# pseudoStateGraphDone.

# 里面整个用 alias 配单引号包起来替代函数可能会速度快一点,但是高亮会废掉。
_opt_flush(){
# alias _opt_flush='
	case "$_list_type" in
		gl)	ARRAY_GL+=("${BUF[@]}");;
		l)	ARRAY_L+=("${BUF[@]}");;
		v)	ARRAY_V+=("${BUF[@]}");;
		"")	return 0;;
		*)	echo What the fuck; return 2;;
	esac
	BUF=()
# ' # End _opt_flush Alias Expansion Def.
}

for opt; do case "$opt" in
	-h|--help)
		usage
		exit 0;;
	-d)
		usage_devel
		exit 0;;
	-gl)
		_opt_flush
		_list_type=gl;;
	-l)
		_opt_flush
		_list_type=l;;
	-v)
		_opt_flush
		_list_type=v;;
        -m)
		_opt_flush
		_list_type=''
		echo "This is a magical example for other opts.";;
	--)
		_opt_flush
		_list_type='';;
	-*)
		echo "What is $opt?";;
	*)
		BUF+=("$opt");;
	esac
done
_opt_flush
declare -p ARRAY_{L,GL,V} BUF

输出这样:

# ./24195 -gl gl1 gl2 gl3 -v v10 v11 -l l1 l2 -l l2 -l l3  -gl gl2 -v v21 gl -- bb cc dd
declare -a ARRAY_L='([0]="l1" [1]="l2" [2]="l2" [3]="l3")'
declare -a ARRAY_GL='([0]="gl1" [1]="gl2" [2]="gl3" [3]="gl2")'
declare -a ARRAY_V='([0]="v10" [1]="v11" [2]="v21" [3]="gl")'
declare -a BUF='([0]="bb" [1]="cc" [2]="dd")'
# ./24195 aa bb cc
declare -a ARRAY_L='()'
declare -a ARRAY_GL='()'
declare -a ARRAY_V='()'
declare -a BUF='([0]="aa" [1]="bb" [2]="cc")'

看了看你的代码,瞻前顾后,想得太多。

最近编辑记录 Arthur2e5 (2015-09-15 04:17:02)


Crawler.

离线

#4 2015-09-15 04:27:56

Arthur2e5
Overuse the Shell!
注册时间: 2015-09-15
帖子: 4
个人网站

Re: 求助:bash中如何提取命令行选项的辅助参数

[csslayer] ˊ_>ˋ 改改你原始命令行参数的方式改成和 getopt 兼容的不是更好
[csslayer] 用单个参数,只不过需要 quote 的形式,或者用逗号
[Arthur2e5] @csslayer 我懒得。
[csslayer] ˊ_>ˋ 我以为你是一开始发帖的……结果是回帖吗,回个 2013 年的贴……
[Arthur2e5] 欸 2013 的吗
+           我去!
+           这版块是有多冷才会 2013 的帖子在第一页
+           jginhaznhNZALIwlinwnheazLnjlxnhLAKAHDKH

什么,这是 2013 的帖子?!T*&@!(*&(*@!#*)#@!


Crawler.

离线

页脚