仓库源文站点原文


layout: post title: 命令行参数的手动处理 categories:


2014-01-30 13:45:22

在编写Bash脚本时, 为了保证脚本的通用性, 有时需要传入命令行参数. 这就需要我们对命令行参数进行解析处理. 虽然说起来很简单, 也有一般的通用处理方法, 但通用的方法总有其不便之处, 知道一些简单的手动处理方法还是很有必要的.

假定处理时参数顺序固定, 读入后被用来设定其他变量值, 若执行

bash Prg.bsh Opt1 Opt2 Opt3

后, 变量P1=Opt1; P2=Opt2; P3=Opt3

最好是先给出变量P1, P2, P3的默认值, 然后根据命令行参数的个数进行设置.

1. quick-and-dirty的if-elif处理

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash if [[ $# -eq 1 ]]; then P1=$1 elif [[ $# -eq 2 ]]; then P1=$1; P2=$2 elif [[ $# -eq 2 ]]; then P1=$1; P2=$2; P3=$3 fi </code></pre>

形式简单点的方式

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash [[ $# -eq 1 ]] && { P1=$1; } [[ $# -eq 2 ]] && { P1=$1; P2=$2; } [[ $# -eq 3 ]] && { P1=$1; P2=$2; P3=$3; } </code></pre>

更聪明点的方式

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash [[ $# -ge 1 ]] && { P1=$1; } [[ $# -ge 2 ]] && { P2=$2; } [[ $# -ge 3 ]] && { P3=$3; } </code></pre>

2. 直接判断参数存在与否

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash [[ -n $1 ]] && { P1=$1; } [[ -n $2 ]] && { P2=$2; } [[ -n $3 ]] && { P3=$3; } </code></pre>

更好点的判断方式

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash [[ x$1 != x ]] && { P1=$1; } [[ x$2 != x ]] && { P2=$2; } [[ x$3 != x ]] && { P3=$3; } </code></pre>

更高级的变量替换方式

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash P1=${1:-Opt1} P2=${2:-Opt2} P3=${3:-Opt3} </code></pre>

3. 利用数组

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash Opt=(Opt1 Opt2 Opt2) for((i=1; i<$#; i++)); do Opt[$i]=${!i} done P1=${Opt[1]} P2=${Opt[2]} P3=${Opt[3]} </code></pre>

上面的处理假定传入参数的顺序是固定的, 当参数个数过多时, 这种限定会使得脚本使用不便. 若传入的各个参数之间没有明显的标志相区别, 一种解决方法就是利用选项了. 先将参数全部存入数组, 然后从中解析出相应的选项, 再根据选项设定相应参数的值. 简单示例代码如下:

<pre class="line-numbers" data-start="0"><code class="language-bash"># Language: bash opt=($@); N=${#opt[@]} for((i=0; i< N; i++)); do arg=${opt[$i]}; j=$((i+1)) [[ $arg =~ -opt1 ]] && { P1=${opt[$j]}; } [[ $arg =~ -opt2 ]] && { P2=${opt[$j]}; } [[ $arg =~ -opt3 ]] && { P3=${opt[$j]}; } opt[$i]=""; opt[$j]="" done </code></pre>

当然, 最通用的方法是利用getoptgetopts, 使用时请参考相应的资料.

参考

  1. Bash Shell中命令行选项/参数处理
  2. Mendel Cooper著, 杨春敏, 黄毅译, 高级Bash脚本编程指南, V3.9.1-HTML-2006年5月26日, 4.4 特殊的变量类型