linux 命令行解析

从windows开发转向linux开发的程序员,实际写代码过程中还是有很多不同的,第一个遇到的不同可能是linux的命令行。windows 应用开发很少有命令行,而linux命令几乎全有命令行,这是因为linux没有操作界面,只能以命令行的方式来切换程序运行不同的命令,或调节命令的参数。比方说你要统计一个文件有多少个字符,在windows下你可以直接用界面操作来选择一个文件,而在linux下你只能通过文件参数来运作。

linux进程的命令行参数一般有,操作源,目标,对操作过程的控制或补充说明。有的命令操作源和目标都有,例如文件复制cp命令。有的只有操作源或目标,例如进入指定目录cd命令。有的操作源,目标都没有,例如显示时间命令date。有些命令行参数也可以看作是子命令,例如yum instatll redis,yum是进程名,install可以看作是他的子命令(或者你可以理解为yum-install),redis是操作源。大部分的linux指令都有操作源或目标。

虽然linux命令行参数的操作源或目标比较单一,但是Linux进程的命令行参数远远没有那么简单,原因是对命令操作过程的控制或补充说明可能会比较复杂。有的控制命令有好几个甚至几十个,当然他们不可能同时都被使用。对于命令行的操作源或目标,一般没有前缀。例如,cp file1 file(其实也可以理解为cp --src file1 --dst file2 )。控制参数一般会有前缀-,而且不同的指令参数的风格还可以不同。例如cp --help,--help只是一个参数,而tar -xzvf,xzvf是四个不同的参数。我们要讨论的是如何正确的解析各种不同的命令行参数。

以常见的git程序来举例,git功能非常强大,他有很多操作,例如add, commit, push, checkout等等,可以把他们看作是git的命令集。

例如,有如下命令:

git commit --amend -m "firt commit"

在上面的例子中,git是进程的名字,commit是git的一个子命令,--amend, -m是命令的参数,"first commit"是参数的值。

在我们的程序中,对于这个命令,我们要正确的解析出子命令commit,提交的描述为"first commit",以及amend ,即提交的补充说明为修改上次的描述。如果我们自己在程序中以解析字符串的方式来解析这些命令行参数,估计要疯掉了。前面说到,命令行参数的样式不一样,没有前缀的,有前缀的,有前缀的风格还不一样。还好Linux 系统给我们提供了一些解析命令行参数的api 解放了苦逼的程序员们。

这些api是getopt,以及增强版的getopt_long。考虑到每个进程用到的命令行参数都可能不一样,getopt把设置命令行参数的权力给了开发者自己,而不是用内定的字符来表示某种含义的参数。前面说了,有的命令行有参数,有的没有,有的既可以有又可以没有。所以要用一种简单的方式,来表示这种含义。所以getopt的原型为:

int getopt(int argc, char *const argv[], const char *optstring);

前面两个参数表示命令行参数的个数(以空格分割)和真实的命令行字符串。optstring可以指定你要设置的参数字符以及参数的风格。例如"a:bc::de"表示这个进程可以有-a的命令行,而且后面必须有参数。例如-a 123或-a123 表示a这个命令行,123是参数(例如gcc 中-lpthread其实是命令行为-l,参数为pthread)。即使是-a -b,-b也要解析为-a的参数。:表示后面必须跟值。b没有冒号表示,只有命令行,没有参数。如果b后面有参数,例如-b123,则解析错误。如果是-b 123,则123与本次的-b无关。有两个::的含义是,例如b::表示命令行可以有参数也可以没有参数,有参数时参数必须紧跟命令行。例如-b123是正确的,表示有一个123参数。而-b 123表示没有参数,123与-b没有关系。

只有没有参数的命令行才能合并,否则会被带参数的命令行解析为参数。例如tar -zxvf,zxvf都为tar的命令行,且没有参数。而带两个--的解析为一个字符串命令行,例如上面的--amend ,amend是一个命令行。解析带两个--的命令行参数需要用到更高级的api,getopt_long。请参考:
https://www.cnblogs.com/chasechoi/p/7644199.html
https://www.cnblogs.com/chenliyang/p/6633739.html

getopt是解析带有-命令行及其参数的。那没有-或--的命令行,例如前面的git commit又该怎么解析呢?其实getopt也帮我们考虑到了,他会修改全局变量optind的值,表示再次调用 getopt() 时的下一个 argv指针的索引。有了这个索引我们可以很方便再次的遍历argv,从而得到commit这个命令行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值