15.bash shell中自定义命令行选项与getopt/getopts

文章目录

  • linux shell 命令行选项
    • 1.命令行选项的手动实现
      • 简单选项
      • 分离命令行参数和选项
      • 带值的选项
      • 合并选项
    • 2.使用 getopt 命令
    • getopts命令
    • 选项标准化


欢迎访问个人网络日志🌹🌹知行空间🌹🌹


linux shell 命令行选项

选项是跟在单破折线后面的单个字母,它能改变命令的行为。

使用命令行参数,需要每次给参数传入需要的值;而使用命令行选项,只需要从支持的选项中选出一个自己需要的选项传入就可以了。

譬如要实现一个支持加减乘除的命令,运算的数值最好写成命令行参数,因为数值有无穷多的可能,而运算的类型最好写成命令行选项,因为毕竟运算只有那么多种。

1.命令行选项的手动实现

简单选项

#!/bin/bash
echo
x=$1
shift
while [ -n "$1" ]docase "$1" in-add) echo "Found the -add option" shiftecho "x + $1 = "$[ x + $1 ] ;;-substract) echo "Found the -substract option" shiftecho "x - $1 = "$[ x - $1 ] ;;-multipy) echo "Found the -multipy option" shiftecho "x * $1 = "$[ x * $1 ] ;;-divide) echo "Found the -divide option" shiftecho "x / $1 = "$[ x / $1 ] ;;*) echo "$1 is not an option" ;;esacshift
done

执行命令,

# bash ./cmd_opt.sh 1 -add 2
# Found the -add option
# x + 2 = 3

分离命令行参数和选项

有时候呢,需要在使用命令行参数的同时使用命令行选项,这个时候呢就需要将两者进行分离。

Linux中处理这个问题的标准方式是用特殊字符来将二者分开,该字符会告诉脚本何时选项结束以及普通参数何时开始。对Linux来说,这个特殊字符是双破折线(--

#!/bin/bashwhile [ -n "$1" ]
docase "$1" in-a) echo "Found the -a option" ;;-b) echo "Found the -b option";;-c) echo "Found the -c option" ;;--) shiftbreak ;;*) echo "$1 is not an option";;esacshift
donecount=1
for param in $@
doecho "Parameter #$count: $param"count=$[ $count + 1 ]
done

运行命令:

# ./cmd_copt.sh -a -b -c -- x y x
# Found the -a option
# Found the -b option
# Found the -c option
# Parameter #1: x
# Parameter #2: y
# Parameter #3: x

带值的选项

有些情况下,需要使用带值的选项。这有些类似于命名参数,之前介绍的命令行参数都是通过$1这种方式读取的,类似于位置参数。

如此,其实只需要在上面介绍的例子上稍加修改就可以了。

# !/bin/bashwhile [ -n "$1" ]
docase "$1" in-a) echo "Found the -a option" ;;-b) echo "Found the -b option"shiftecho "\tValue of -b option is $1" ;;-c) echo "Found the -c option" ;;--) shiftbreak ;;*) echo "$1 is not an option";;esacshift
donecount=1
for param in $@
doecho "Parameter #$count: $param"count=$[ $count + 1 ]
done

执行结果:

# ./cmd_copt.sh -a -b value_b -c -- x y x# Found the -a option
# Found the -b option
# \tValue of -b option is value_b
# Found the -c option
# Parameter #1: x
# Parameter #2: y
# Parameter #3: x

合并选项

Linux中使用命令时,经常会用到将几个参数写在一起,如ls -alh,ps -aux等等,自己动手实现这种命令行选项该如何操作呢?还是coding from scratch的话,自己造轮子就太麻烦了,好在Linux中提供了getopt/getopts命令来处理命令行选项和参数。

2.使用 getopt 命令

命令格式:

getopt optstring parameters

optstring定义了命令行有效的选项字母,还定义了哪些选项字母需要参数值。getopt会基于给定的 optstring 解析提供的参数。 parameters定义了命令行参数有哪些。

该命令的使用方法为:

  • 首先,在 optstring列出要在脚本中用到的每个命令行选项字母
  • 然后,在每个需要参数值的选项字母后加一个冒号

如下:

getopt ab:cd -a -b value_b -cd param1 param2
# -a -b value_b -c -d -- param1 param2

上面调用getopt命令的示例中,optstringab:cd parameters-a -b value_b -cd param1 param2,可以看到value_b被解析成了选项b的值,合并的选项-cd被分别拆开了。并插入双破折线来分隔行中的额外参数,param1 param2是作为命令行参数出现的。

如果指定了一个不在 optstring 中的选项,默认情况下, getopt 命令会产生一条错误消息。

getopt ab -abc
# getopt: 不适用的选项 -- c

在脚本中该如何使用getopt呢?

set命令能够处理shell中的各种变量。set 命令会显示为某个特定进程设置的所有环境变量。set 命令的选项之一是双破折线( -- ),它会将命令行参数替换成 set 命令的命令行值。该方法会将原始脚本的命令行参数传给 getopt 命令,之后再将 getopt 命令的输出传
set 命令,用 getopt 格式化后的命令行参数来替换原始的命令行参数。

set -- $(getopt -q ab:cd "$@")

如此,可以将前面的脚本改写,使其支持选项参数合并等操作。

# !/bin/bashset -- $(getopt -q ab:c "$@")while [ -n "$1" ]
docase "$1" in-a) echo "Found the -a option" ;;-b) echo "Found the -b option"shiftecho "\tValue of -b option is $1" ;;-c) echo "Found the -c option" ;;--) shiftbreak ;;*) echo "$1 is not an option";;esacshift
donecount=1
for param in $@
doecho "Parameter #$count: $param"count=$[ $count + 1 ]
done# ./cmd_copt.sh -ac -b valueB valueD valueE valueF
# Found the -a option
# Found the -c option
# Found the -b option
# \tValue of -b option is 'valueB'
# Parameter #1: 'valueD'
# Parameter #2: 'valueE'
# Parameter #3: 'valueF'

不过,getopt还存在一个不足,那就是处理带空格的参数值时会出错。

./cmd_copt.sh -ac -b valueB "this is valueD" valueF
# Found the -a option
# Found the -c option
# Found the -b option
# \tValue of -b option is 'valueB'
# Parameter #1: 'this
# Parameter #2: is
# Parameter #3: valueD'
# Parameter #4: 'valueF'

可以看到,this is valueD还是被拆分了。这就要引入一个更复杂也更强大的命令getopts

getopts命令

getopts内建于bash shell,比getopt命令多了一些扩展功能。

getopt将命令行上选项和参数处理后只生成一个输出,而 getopts 命令每次被调用时,它一次只处理命令行上检测到的一个参数。处理完所有的参数后,它会退出并返回一个大于0的退出状态码。这让它非常适合用解析命令行所有参数的循环中,因此,能够和已有的shell参数变量配合默契。

getopts命令的格式如下:

getopts optstring variable

optstring 值作用类似于 getopt 命令。getopts 命令将当前参数保存在命令行中定义的 variable 中。

getopts 命令会用到两个环境变量OPTARGOPTIND。如果选项需要跟一个参数值, OPTARG 环境变量就会保存这个值。OPTIND 环境变量保存了参数列表中 getopts 正在处理的参数位置。

使用getopts的例子:

#!/bin/bashwhile getopts :ab:c opt
docase "$opt" ina) echo "Found the -a option" ;;b) echo "Found the -b option, with value $OPTARG";;c) echo "Found the -c option" ;;*) echo "Unknown option: $opt";;esac
done

在本例中 case 语句的用法有些不同。getopts 命令解析命令行选项时会移除开
头的单破折线,所以在 case 定义中不用单破折线。

执行,

支持带引号的参数值:

./test_opts.sh -ab 'this is valueB' -c
# Found the -a option
# Found the -b option, with value this is valueB
# Found the -c option

将选项字母和参数值放在一起使用时,可以不用加空格

./test_opts.sh -abValueB
# Found the -a option
# Found the -b option, with value ValueB

getopts 还能够将命令行上找到的所有未定义的选项统一输出成问号

./test_opts.sh -abValueB -de# Found the -a option
# Found the -b option, with value ValueB
# Unknown option: ?
# Unknown option: ?

optstring 中未定义的选项字母会以问号形式发送给代码。

getopts 命令知道何时停止处理选项,并将参数留给程序员处理。

getopts 处理每个选项时,它会将 OPTIND 环境变量值增一。在 getopts 完成处理时,可以使用 shift 命令和 OPTIND 值来移动参数。

#!/bin/bash
#
echo
while getopts :ab: opt
docase "$opt" ina) echo "Found the -a option" ;;b) echo "Found the -b option, with value $OPTARG" ;;*) echo "Unknown option: $opt" ;;esac
done
#
shift $[ $OPTIND - 1 ]
#
echo
count=1
for param in "$@"
doecho "Parameter $count: $param"count=$[ $count + 1 ]
done

执行,

./test_opts.sh -a -b ValueB 1 2 "3 4"# Found the -a option
# Found the -b option, with value ValueB# Parameter 1: 1
# Parameter 2: 2
# Parameter 3: 3 4

选项标准化

在创建shell脚本时,完全可以决定用哪些字母选项以及它们的用法。但有些字母选项在Linux世界里已经拥有了某种程度的标准含义。如果能在shell脚本中支持这些选项,脚本看起来能更友好一些。

Linux中用到的一些命令行选项的常用含义:

选项描述
-a显示所有对象
-c生成一个计数
-d指定一个目录
-e扩展一个对象
-f指定读入数据的文件
-h显示命令的帮助信息
-i忽略文本大小写
-l产生输出的长格式版本
-n使用非交互模式(批处理)
-o将所有输出重定向到的指定的输出文件
-q以安静模式运行
-r递归地处理目录和文件
-s以安静模式运行
-v生成详细输出
-x排除某个对象
-y对所有问题回答yes



欢迎访问个人网络日志🌹🌹知行空间🌹🌹


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/594979.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL基础篇(一)SQL

视频地址: 黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括 SQL,全称 Structured Query Language,结构化查询语言。操作关系型数据库的编程语言,定义了一套操作关系型数据库统一 标准。 一、SQL通用语…

整数的阶乘(英语:factorial)是所有小于及等于

整数的阶乘(英语:factorial)是所有小于及等于该数的正整数的积,0的阶乘为1。即:n!123...n。 实例 #!/usr/bin/python3 # Filename : test.py # author by : www.dida100.com # 通过用户输入数字计算阶乘 # 获…

electron自定义菜单

创建menu.js const { app, Menu } require("electron"); const createMenu () > {const menu [{label: "菜单",submenu: [{label: "新增",click: () > {},}, ],},{label: "关于",submenu: [{label: "新增",click:…

Java数据结构:1. 数据结构前置知识

文章目录 一、初识数据结构二、初识集合框架1. 什么是集合框架2. 集合框架的重要性3. 背后所涉及的数据结构以及算法 三、时间复杂度空间复杂度1. 算法效率2. 时间复杂度(1)概念(2)大O的渐进表示法(3)推导大…

MySQL5.7用于控制副本服务器的 SQL 语句

官网地址:MySQL :: MySQL 5.7 Reference Manual :: 13.4.2 SQL Statements for Controlling Replica Servers 欢迎关注留言,我是收集整理小能手,工具翻译,仅供参考,笔芯笔芯. MySQL 5.7 参考手册 / ... / CHANGE M…

C语言多线程编程-线程间通信

介绍 在C语言中,采用多线程编程,我们经常会遇到,线程之前需要同步数据,或者一个线程处理后的的数据,需要给另外一个线程进行处理,这就需要线程之间进行通讯,多线程间的通信和同步是通过操作系统…

计算机系统基础

C 语言相关内容省略,复习自用,仅供参考~ 概述 冯诺伊曼结构 存储程序工作方式:将事先编好的程序和原始数据送入主存后才能执行程序,程序被启动执行后,计算机能在不需要操作人员干预下自动完成逐条指令取出和执行的任…

Toast.makeText()的使用方法

Toast.makeText()的使用方法 大家好,我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!在今天的文章中,我们将深入讨论Android开发中一个常用而且便捷的UI组件——…

奋楫扬帆,奔赴新程 | 2023 年图扑大事记回顾,与您携手共迎 2024

2023.01 工信部公示了 2022 年度智能制造示范工厂揭榜单位和优秀场景名单。图扑软件和上海洲邦合作建设的宁波甬友数字孪生工厂被评为优秀场景,全国共有 369 个智能制造典型场景入选。 2023.01 在第十一届中国创新创业大赛全国赛(新一代信息技术&#…

RabbitMQ(八)消息的序列化

目录 一、为什么需要消息序列化?二、常用的消息序列化方式1)Java原生序列化(默认)2)JSON格式3)Protobuf 格式4)Avro 格式5)MessagePack 格式 三、总结 RabbitMQ 是一个强大的消息中间…

Hadoop分布式文件系统(二)

一、Hadoop 1、文件系统 1.1、文件系统定义 文件系统是一种存储和组织数据的方法,实现了数据的存储、分级组织、访问和获取等操作,使得用户对文件访问和查找变得容易。 文件系统使用树形目录的抽象逻辑概念代替了硬盘等物理设备使用数据块的概念&#…

通信基础——带宽

随着信息社会的发展和数字化进程的加速,通信技术已经成为现代社会最为重要的基础设施之一。而在通信技术中,带宽作为一个重要的概念,对于我们理解和应用现代通信技术具有至关重要的意义。本文将以“通信基础——带宽”为主题,对带…

高性能NVMe Host Controller IP

NVMe Host Controller IP 介绍 NVMe Host Controller IP可以连接高速存储PCIe SSD,无需CPU和外部存储器,自动加速处理所有的NVMe协议命令,具备独立的数据写入AXI4-Stream/FIFO接口和数据读取AXI4-Stream/FIFO接口,非常适合于超高…

华芯微特MCU之TIMER触发ADC

01 TIMER定时器之脉冲发送功能 我们今天详细讲解一下TIMER的ADC触发功能。 SWM190的TIMER2/3支持SAR ADC触发功能,此功能配置为定时器或脉冲发送均有效,可通过配置相应寄存器实现。 将SAR ADC CTRL寄存器中TRIG设置为TIMER2触发或TIMER3触发。TIMER可作…

技术旅程分享:收获与成长的探索

2023年对我而言是充满挑战和机遇的一年,我在这段时间里积累了丰富的技术经验和个人成长。通过不懈努力和持续学习,我在技术领域迈出了一系列坚实的步伐。在这篇文章中,我将分享我在这段时间中的收获和技术成长经历,与CSDN的朋友们…

数据库存储过程

存储过程(特定功能的 SQL 语句集) 一组为了完成特定功能的 SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是…

vue的小入门

vue的快速上手 Vue概念 是一个用于构建用户界面的渐进式框架优点:大大提高开发效率缺点:需要理解记忆规则 创建Vue实例 步骤: 准备容器引包创建Vue实例new Vue()指定配置项el data>渲染数据 el指定挂载点,选择器指定控制…

解决burpsuite代理8080端口无法勾选以及卸载NI系列软件的方法

使用burpsuite中遇到这样一个问题 默认的8080端口无法绑定 提示端口已经被占用 尝试绑定其他端口,是可行的,也可以正常抓包 但是总感觉每次进来都设置添加一次,有点麻烦不舒服 那么我们来看一下8080端口到底被什么进程占用了 使用如下命令…

计算机视觉中的神经网络可视化工具与项目

前言 本文介绍了一些关于神经网络可视化的项目,主要有CNN解释器,特征图、卷积核、类可视化的一些代码和项目,结构可视化工具,网络结构手动画图工具。 CNN解释器 这是一个中国博士发布的名叫CNN解释器的在线交互可视化工具。 主要…

下载的 MongoDB bin目录下没有mongo.exe文件问题解决

MongoDB 4.4版本之前,我们可以在MongoDB的安装目录的bin文件夹中找到mongo.exe这个命令行工具。但是从MongoDB 4.4版本开始,MongoDB官方已经不再提供独立的mongo.exe可执行文件,而是将其整合到了mongosh这个新的交互式Shell中。 我们可以访问…