Linux处理用户输入

目录

一、传递参数

1.1 读取参数

1.2 读取脚本名

二、跟踪参数

三、移动参数

四、处理选项

4.1 查找选项

4.1.1 处理简单选项

4.1.2 分离参数和选项

 4.1.3 处理含值的选项

五、选项标准化

5.1 使用 getopt 命令 

5.1.1 命令格式

5.1.2 在脚本中使用getopt

 5.2 使用getopts命令

六、获取用户输入

6.1 read读取 

6.2 从文件中读取


一、传递参数

向 shell 脚本传递数据的最基本方法是使用命令行参数。bash shell 会将所有的命令行参数都指派给称作位置参数的特殊变量。这也包括shell脚本名称。位置变量的名称都是标准数字,$0 对应脚本名,$1 对应第一个命令行参数,$2 对应第二个命令行参数,以此类推,直到 $9,第9个之后,必须在变量名两侧加上花括号,比如 ${10} 。

1.1 读取参数

如果需要 输入更多的命令行参数,则参数之间必须用空格分开

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat position.sh
#! /bin/bashvalue=$[ ${10} * ${11} ]
echo "第10个参数是${10}"
echo "第11个参数是${11}"
echo $value
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ./position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

1.2 读取脚本名

 可以使用位置变量 $0 获取在命令行中运行的脚本名。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat position.sh
#! /bin/bashvalue=$[ ${10} * ${11} ]
echo "第10个参数是${10}"
echo "第11个参数是${11}"
echo $value
echo "脚本名是$0"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
脚本名是position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

 但是这会有一个问题,如果使用另一个命令运行shell脚本,则命令名会和脚本名混在一起

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat position.sh
#! /bin/bashvalue=$[ ${10} * ${11} ]
echo "第10个参数是${10}"
echo "第11个参数是${11}"
echo $value
echo "脚本名是$0"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
脚本名是position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ./position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
脚本名是./position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

 这还不是唯一的问题,如果运行脚本时使用的是绝对路径,那么位置变量 $0 就会包含整个路径

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# pwd
/root
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ~/position.sh
/root/position.sh: line 3: *  : syntax error: operand expected (error token is "*  ")
第10个参数是
第11个参数是脚本名是/root/position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

basename 命令可以返回不包含路径的脚本名 

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat position.sh
#! /bin/bashvalue=$[ ${10} * ${11} ]
echo "第10个参数是${10}"
echo "第11个参数是${11}"
echo $value
name=$(basename $0)
echo "脚本名是$name"
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ./position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
脚本名是position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

 利用此技术可以编写一个脚本,生成能标识脚本运行时间的日志信息

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat position.sh
#! /bin/bashvalue=$[ ${10} * ${11} ]
echo "第10个参数是${10}"
echo "第11个参数是${11}"
echo $value
name=$(basename $0)
echo "脚本名是$name"
echo "The $name ran at $(date)" >> ~/scripttrack.log
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# date
Fri May 10 15:42:54 CST 2024
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ./position.sh 1 2 3 4 5 6 7 8 9 10 12
第10个参数是10
第11个参数是12
120
脚本名是position.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# ll
total 12
-rwxr--r-- 1 root root  210 May 10 15:42 position.sh
drwxr-xr-x 2 root root 4096 May  9 23:36 script
-rw-r--r-- 1 root root   52 May 10 15:43 scripttrack.log
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat scripttrack.log
The position.sh ran at Fri May 10 15:43:01 CST 2024
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

二、跟踪参数

特殊变量 $# 含有脚本运行时携带的命令行参数的个数,${!#} 代表最后一个位置变量,$*$@ 各自包含了所有的命令行参数。$* 将所有参数视为一个整体,$@ 会将所有命令行参数视为同一字符串中的多个独立的单词,可以用 for 遍历所有参数。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat params.sh
#! /bin/bash
echo
echo "\$*用法:$*"
count=1
for param in "$*"
doecho "\$* #$count = $param"count=$[ $count + 1 ]
done########
echo
echo "\$@用法:$@"
count=1
for param in "$@"
doecho "\$@ #count = $param"count=$[ $count +1 ]
done
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash params.sh 1 2 3$*用法:1 2 3
$* #1 = 1 2 3$@用法:1 2 3
$@ #count = 1
$@ #count = 2
$@ #count = 3
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

三、移动参数

shift 命令会根据命令行参数的相应位置进行移动,默认情况下会将每个位置的变量值都向左移动一个位置。因此,变量 $3 的值会移入 $2 ,变量 $2 的值会移入 $1 ,而变量 $1 的值会被删除(变量 $0 是脚本名,不会变)。这是遍历命令行参数的另一种好方法,尤其在不知道到底有多少参数的时候。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat shift.sh
#! /bin/bash
echo
echo "shift的用法"
count=1
while [ -n "$1" ]
doecho "#$count = $1"count=$[ $count + 1 ]shift
done
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash shift.sh ab cd 12 34 dfshift的用法
#1 = ab
#2 = cd
#3 = 12
#4 = 34
#5 = df
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

四、处理选项

4.1 查找选项

在命令行中,选项紧跟在脚本名之后,就跟其他命令行参数一样 。你可以像处理命令行参数一样处理命令行选项

4.1.1 处理简单选项

 在提取单个参数时,使用  case 语句来判断某个参数是否为选项

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# vim option.sh
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat option.sh
#! /bin/bash
echo
while [ -n "$1" ]
docase "$1" in-a) echo "a是一个选项";;-b) echo "b是一个选项";;-c) echo "c是一个选项";;*) echo "$1不是一个选项";;esacshift
done
echo
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -b -a e -fb是一个选项
a是一个选项
e不是一个选项
-f不是一个选项[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

4.1.2 分离参数和选项

 经常会碰到同时使用选项和参数的情况。在Linux系统中,处理这个问题的标准做法是使用特殊字符将两者分隔,该字符告诉脚本选项何时结束,普通字符何时开始。在Linux系统中这个特殊字符是双连字符(--)。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat option.sh
#! /bin/bash
echo
while [ -n "$1" ]
docase "$1" in-a) echo "-a是一个选项";;-b) echo "-b是一个选项";;-c) echo "-c是一个选项";;--) shiftbreak;;*) echo "$1不是一个选项";;esacshift
done
#
echo
count=1
for param in "$@"
doecho "参数#$count = $param"count=$[ $count + 1 ]
done
echo
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -b -a -d -- 1 21 6-b是一个选项
-a是一个选项
-d不是一个选项参数#1 = 1
参数#2 = 21
参数#3 = 6[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

在遇到双连字符时,脚本会用break命令跳出while循环。由于提前结束了循环,因此需要再加入另一个shift命令将双连字符移除位置变量 

 4.1.3 处理含值的选项

有些选项需要一个额外的参数值,像下面这样

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat option.sh
#! /bin/bash
echo
while [ -n "$1" ]
docase "$1" in-a) echo "-a是一个选项";;-b) echo "-b是一个选项"echo "参数$2"shift ;;-c) echo "-c是一个选项";;--) shiftbreak;;*) echo "$1不是一个选项";;esacshift
done
#
echo
count=1
for param in "$@"
doecho "参数#$count = $param"count=$[ $count + 1 ]
done
echo
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -b test -a -d -- 1 21 6-b是一个选项
参数test
-a是一个选项
-d不是一个选项参数#1 = 1
参数#2 = 21
参数#3 = 6[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

在这个例子中,case语句定义了3个要处理的选项。-b选项还需要一个额外的参数。由于要处理的选项位于 $1 ,因此额外的参数值就应该位于 $2 ,因为选项占用了两个位置,所以还需要使用 shift 命令多移动一次。 

五、选项标准化

现在shell脚本已经拥有处理命令行选项的基本能力了,但是当你想合并多个选项时,脚本就不管用了。

5.1 使用 getopt 命令 

5.1.1 命令格式

getopt 命令可以接受一系列任意形式的命令行选项和参数,并自动将其转换为适当格式。getopt 格式如下:getopt optstring parameters 

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

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# getopt ab:cd -a -b value -cd 1 2-a -b value -c -d -- 1 2
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

 如果 optstring 未包含制定的选项,则会输出一条错误信息,如果想忽略,可以使用 -q 选项。

5.1.2 在脚本中使用getopt

 1)可以在脚本中使用 getopt 格式化脚本所携带的任何命令行选项或参数。难点在于使用 getopt 格式化版本替换已有的命令行选项和参数。这得求助于 set 命令;

2)set 命令有个选项是双连字符(--),可以将位置变量的值替换为 set 命令所指定的值;

3)具体做法是将脚本的命令行参数传递给getopt命令,然后将getopt命令的输出传递给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数,如下所示: 

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

 现在,位置变量原先的值会被getopt命令的输出替换掉,后者已经是格式化好的命令行参数。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat option.sh
#! /bin/bashset -- $(getopt -q ab:cd "$@")
echo
while [ -n "$1" ]
docase "$1" in-a) echo "-a是一个选项";;-b) echo "-b是一个选项"echo "参数$2"shift ;;-c) echo "-c是一个选项";;--) shiftbreak;;*) echo "$1不是一个选项";;esacshift
done
#
echo
count=1
for param in "$@"
doecho "参数#$count = $param"count=$[ $count + 1 ]
done
echo
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -ab bvalue 12 3-a是一个选项
-b是一个选项
参数bvalue参数#1 = 12
参数#2 = 3[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

 5.2 使用getopts命令

getopt 命令存在一个问题,如下代码所示:就是不擅长处理带空格和引号的参数值。它会将空格当做参数值的分隔符,而不是根据双引号将二者当做一个参数。这是 getopts 就派上用场了。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -ab bvalue 12 3 -c-a是一个选项
-b是一个选项
参数bvalue
-c是一个选项参数#1 = 12
参数#2 = 3[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash option.sh -ab bvalue "12 3" -c-a是一个选项
-b是一个选项
参数bvalue
-c是一个选项参数#1 = 12
参数#2 = 3

 getopts 命令格式如下:

getopts optstring variable

1) optstring 值与 getopt 命令中使用的类似。有效的选项字母会在 optstring 中列出,如果选项要求参数,就在其后面加一个冒号。不想显示错误消息的话,可以在 optstring 之前加一个冒号。getopts 会将当前参数保存在命令行中定义的varibales中。

2)getopts 会用到两个环境变量。如果选项需要加带参数值,那么 OPTARG 环境变量保存的就是这个值。OPTIND 环境变量保存着参数列表中 getopts 正在处理的参数位置。这样在处理完当前选项之后就能继续处理其他命令行参数了。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat getopts.sh
#! /bin/bash
echo
while getopts :ab:cd opt
docase "$opt" ina) echo "-a是选项";;b) echo "-b是一个选项"echo "-b选项的参数是$OPTARG";;c) echo "-c是一个选项";;*) echo "未知选项$opt";;esac
done
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash getopts.sh -ab2-a是选项
-b是一个选项
-b选项的参数是2
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

1) 在解析命令行选项时,getopts 会移除起始的连字符,所以 case 语句中不用连字符;

2)可以在参数值中加空格;

3)可以将选项字母和参数值写在一起,两者之间不加空格;

4)在处理每个选项时,getopts 会将OPTIND 环境变量的值增1.处理完选项后,可以使用shift命令和OPTIND值来移动参数。

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat getopts.sh
#! /bin/bash
echo
while getopts :ab:cd opt
docase "$opt" ina) echo "-a是选项";;b) echo "-b是一个选项"echo "-b选项的参数是$OPTARG";;c) echo "-c是一个选项";;*) echo "未知选项$opt";;esac
done
#
shift $[ $OPTIND -1 ]
echo
count=1
for param in "$@"
doecho "参数#$count = $param"count=$[ $count + 1 ]
done
exit

六、获取用户输入

尽管命令行选项和参数是从脚本用户处获取输入的一种重要方式,但有时候脚本还需要更多

的交互性。为此,bash shell 提供了 read 命令。 

6.1 read读取 

read -p "Please enter your age:" age
read -t 5 -p "Please enter your age:" age # 超时
read -s "Enter your password:" password # 无显示输出

6.2 从文件中读取

[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# cat read.sh
#! /bin/bash
echo
count=1
cat ~/getopts.sh | while read line
doecho "#$count = $line"count=$[ $count + 1 ]
done
echo "处理完文本的所有行"
exit
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]# bash read.sh#1 = #! /bin/bash
#2 = echo
#3 = while getopts :ab:cd opt
#4 = do
#5 = case "$opt" in
#6 = a) echo "-a是选项";;
#7 = b) echo "-b是一个选项"
#8 = echo "-b选项的参数是$OPTARG";;
#9 = c) echo "-c是一个选项";;
#10 = *) echo "未知选项$opt";;
#11 = esac
#12 = done
#13 = #
#14 = shift $[ $OPTIND -1 ]
#15 = echo
#16 = count=1
#17 = for param in "$@"
#18 = do
#19 = echo "参数#$count = $param"
#20 = count=$[ $count + 1 ]
#21 = done
#22 = exit
处理完文本的所有行
[root@iZbp1ir1vzqwzkdy7mvjthZ ~]#

while 循环会持续通过read命令处理文件中的各行,直到read命令以非0退出状态码退出

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

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

相关文章

Python小程序 - 文件处理1(使用AI工具)

使用 AI进行Python 小程序开发,会是什么样子的:只要你问的准,AI给出的答案?自己试试看,入门越来越低。 人还要做什么?还能做什么? 需求:给定目录 -- 需求持续补充中 1&#…

船舶检测数据集VOC+YOLO格式7000张6类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):7000 标注数量(xml文件个数):7000 标注数量(txt文件个数):7000 标注…

文件夹列表命令

ls > filenames.txt 列出本文件夹内文件 find ~/docs -type f -maxdepth 1 > filenames.txt 如果只需要在目录中立即包含的常规文件的名称,那么可以这样:

【linux-IMX6ULL-定时器-GPT-串口配置流程-思路】

目录 1. 定时器配置流程1.1 EPIT定时器简介1.2 定时器1(epit1)的配置流程1.3 配置代码(寄存器版本)1.4 定时器-配合按键消抖1.4.1 实现原理1.4.2 代码实现(寄存器版) 2. GPT定时器实现高精度延时2.1 延时原理分析2.2 代码实现 3. UART串口配置流程3.1 UA…

微信小程序按钮去除边框线

通常我们去掉按钮边框直接设置 border:0 但是在小程序中无效,设置outline:none也没用,当然可能你会说加权重;试过了无效 实际上该样式是在伪元素::after内,主要你检查css 还看不到有这个关系,鹅厂就是坑多 类样式::…

半小时搞懂STM32面经知识点——IIC

1.IIC 1.1什么是IIC? 同步半双工通信协议,适用于小数据和短距离传输。 1.2 IIC需要几条线? IIC总共有2条通信总线(SDA,SCL),SCL为时钟同步线,用于主机和从机间数据同步操作;SDA为…

【密评】 | 商用密码应用安全性评估从业人员考核题库(9/58)

Hill密码是重要古典密码之一,其加密的核心思想的是()。 A.线性变换 B.非线性变换 C.循环移位 D.移位 著名的Kerckhoff原则是指()。 A.系统的保密性不但依赖于对加密体制或算法的保密,而且依赖于密钥 B.系统…

【计算机网络】数据链路层的功能

数据链路层的基本功能: 封装成帧透明传输差错检测 数据链路层使用的信道主要有两种 点对点信道——PPP协议广播信道——CSMA/CD协议(有线局域网)、CSMA/CA协议(无线局域网) 数据链路层所处的地位 从图中可以看出,数据从主机H1送到主机H2需要在路径中…

论文笔记模版

1. 摘要 1.1 背景 1.2 挑战 1.3 提出新方法 1.4 贡献 2. 引言 2.1 背景(引出问题) ①介绍大背景: ② 应用场景: ③ 介绍主题: 2.2 引出挑战 一般用图表来展现出我们的挑战(直观,解决什…

echarts环形图 legend文字过长显示...鼠标移动上展示全称

legend: {type: scroll,orient: vertical,x: left,y: bottom,top: "42%",left: 13%,data: this.dutyNames,textStyle: { color: #fff },triggerEvent: true,tooltip: {show: true,trigger: item,//鼠标移动上去展示全称},formatter: function (params) {var val &qu…

HTML五彩缤纷的爱心

写在前面 小编准备了一个五彩缤纷的爱心,送给各位小美女们~ 在桌面创建一个.txt文本文件,把代码复制进去,将后缀.txt改为.html,然后就可以双击运行啦! HTML简介 HTML(超文本标记语言)是一种…

【Python单点知识】通过实例介绍抽象类

文章目录 0. 前言1. 抽象类的概念与特性1.1 定义1.2 特性 2. 抽象类的实现与使用2.1 抽象类的创建2.2 抽象类的特性验证2.3 注册机制与非直接继承 3. 应用场景与设计价值4. 总结 0. 前言 按照国际惯例,首先声明:本文只是我自己学习的理解,虽然…

C++——二叉树搜索树

前面写了初阶数据结构——二叉树;本文内容是来对它来进行结尾 目录 一概念 二实现 2.1查找 2.2插入 2.3删除 完整源代码 三二叉树的应用 四二叉搜索树的性能分析 五二叉搜索树相关的面试题 一概念 二叉搜索树又称二叉排序树,它或者是一棵空树…

妙笔生花,创作无限——WonderPen妙笔 for Mac

写作,是灵感的流淌,是心灵的独白。WonderPen妙笔 for Mac,为您的灵感插上翅膀,让您的创作更加流畅自如。它拥有简洁直观的界面设计,让您的思绪在纯净的写作环境中自由飞翔。多种写作模式,满足您不同的创作需…

Ps 滤镜:绘图笔

Ps菜单:滤镜/滤镜库/素描/绘图笔 Filter Gallery/Sketch/Graphic Pen 绘图笔 Graphic Pen滤镜可以模拟传统绘画技术,特别是模拟使用细油墨笔进行绘制的艺术效果。该滤镜主要用于将图像中的细节以细线的形式表现出来,非常适合于增强图像的线条…

c语言题库之多个数组从两边移动向中间汇聚

文章目录 题目分析代码实现代码分析 题目 c语言题库之多个数组从两边移动向中间汇聚 呈现效果:输入想要输入的字符数组呈现数组从两边向中间逐渐打开的样子 分析 首先我们需要一组我们想要输入的字符数组用来展示打开的字符其次我们需要进行对数组的替换&#x…

系统加固-自用

一、windows 1、概述 (1)、权限最高:system(系统账户),权限比administrator权限还高 (2)、常见操作系统安全漏洞类型 缓冲区溢出漏洞TCP/IP协议漏洞web应用安全漏洞开放端口的安全漏洞 2、系统安全加固方法 (1)、系统不显示上次登录的用户名 进入…

nss刷题(2)

1、[NSSCTF 2022 Spring Recruit]ezgame 打开题目是一个游戏界面 发现是有分数的,猜测分数达到某个之后可以获得flag,查看源码看一下 看到末尾显示分数超过65后显示flag 在js中找到了一个score,将他的值改为大于65的数后随意玩一次就可以得到flag同时&a…

【设计模式】之代理模式(两种)

系列文章目录 (其他设计模式可以参考 👉👉👉)设计模式_小杰不秃头的博客 😊😄😛 前言 今天继续给大家介绍23种设计模式中的代理模式,熟悉Spring的小伙伴都知道&#xf…

文心一言指令:解锁AI写作的新纪元

文心一言指令:解锁AI写作的新纪元 一、引言 在人工智能(AI)飞速发展的今天,自然语言处理(NLP)技术取得了显著的进步。文心一言,作为NLP领域的一颗璀璨明星,以其强大的文本生成和指令…