linux中getopts与shift的冲突之处

本文详细解析了一个使用getopts和shift的Shell脚本,通过实例展示了参数处理过程中的细节和常见误解,特别是对于getopts如何根据选项在命令行中的偏移进行判断以及shift对参数位置的影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

整个文章使用的测试代码如下:

<pre name="code" class="plain">#!/bin/sh

while getopts "abc:" opt
do
	case $opt in
		"a" ) echo a.$1;;	
		"b" ) echo b.$1;;
		"c" ) echo c.$1,$OPTARG;;
	esac	
	echo optindex:$OPTIND,args:$#
	shift 
done


对于该脚本,如果使用命令 ./test.sh -a -b -c 123,那么输出应该是什么呢?

一开始,我认为应该是这个样子的:

a.-a
optindex:2,args:4
b.-b
optindex:3,args:3
c.-c,123
optindex:4,args:2

</pre><p><span style="font-size:12px">但是实际上,输出却是如下:</span></p><p></p><pre name="code" class="plain"><pre name="code" class="plain">gls@ubuntu:~/doc/scripts$ ./test.sh -a -b -c 123 
a.-a,-b
optindex:2,args:4
c.-b,123,123
optindex:4,args:3
gls@ubuntu:~/doc/scripts$



上面的结果有两个出乎意料的地方:


<pre name="code" class="plain">1、为什么只输出了两次?(case)
2、为什么case中的-b没有进入判断?


其实大家很容易得出什么地方可能会引起这样的问题——shift,但是具体的原因,却有待说明。

因为我对于getopts的具体实现不清楚,因此只能给出自己的猜测,并给出对应的证明。

我的猜测是这样的:1、getopts根据选项在命令行中的偏移来判断该选项位置。在例子中,第一个选项为参数开始位置算起的第一个(简单记为#1),为-a,第二位参数看是位置的第二个(记为#2),为-b,依此类推。那么,一个很重要的信息就是:哪个地方是参数的开始位置呢——毫无疑问,应该是$1。而使用shif恰恰会影响$1的位置(参考shift的作用)。

基于这个猜测,我就能解释上面的两个问题。

   很显然,第一次的输出不难理解(第一次输出为第一、二行)。至于第二次输出,则是因为如下原因:使用了shift,导致参数的相对位置发生了变化,$1对应的是-b选项,也就是说此时的-b的位置成了#1(从$1算起的第一个参数)。当getopts处理完第一个选项,准备去取第二个选项时(也就是#2),由于已经发生了偏移,此时的#2为-c,那么就会进入-c(case分支的判断),也就是说直接略过-b的选项。因此,出现了只有两个选项,且-b没有进入判断。

至于验证,也很简单。还是上面的代码。改变参数即可。

<pre name="code" class="plain">gls@ubuntu:~/doc/scripts$ ./test.sh -a -b -c 123 -b -a
a.-a,-b
optindex:2,args:6
c.-b,123,123
optindex:4,args:5
a.-c,123
optindex:5,args:4
gls@ubuntu:~/doc/scripts$ 


前面两次输出是一样的,只是多了一次输出。可以不难发现,此时的选项有5个!

具体是怎么样的,还得基于刚才的假设,前面的两次与第一次解释一致。至于第三次:

第三次输出是,已经使用了两次shift,$1对应的是-c(第5行的-c可以说明)。也就是说,此时的#1应该对于的是-c。至此,getopts已经解析了2个参数,正要解析第三个参数。而第三个参数,在它看来,应该在#3的位置,而此时#3对应的什么?—-从-c算起的第三个选项,没错,正是-a选项。此时第三次的输出也正是-a应该对应的输出。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值