(六)Shell编程之函数、脚本引用、符号展开、重定向

news/2024/4/19 10:31:33/文章来源:https://blog.csdn.net/Sean_0819/article/details/127225944

一、定义函数

shell中函数的定义格式如下:

[ function ] funname [()]
{action;[return int;]
}

说明:

  • 可以带function fun()定义,也可以直接fun()定义,如果带function函数名后的小括号可以省略。
  • 返回值语句[return int;]可以不写,如果不加,将以最后一条命令运行结果,作为返回值。注意return只能返回一个数值n(0-255)

下面我们直接举个栗子🌰~

#!/bin/bashfirstFun () {echo "这是我的第一个 shell 函数!"
}
function secondFun {echo "这是我的第二个 shell 函数!"
}
echo "-----函数开始执行-----"
firstFun
secondFun
echo "-----函数执行完毕-----"

 输出结果:

再来一个栗子🌰~

#!/bin/bash
funWithReturn () {echo "这个函数会对输入的2个数字进行相加运算"echo "输入第一个数字: "read aNumecho "输入第二个数字: "read anotherNumecho "两个数字分别为 $aNum 和 $anotherNum !"return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"

 输出结果:

注意: 函数的返回值在调用该函数后可以通过   $?  来获得

所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至shell解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

二、函数参数

在shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数...

下面我们直接举个栗子🌰~

#!/bin/bash
funWithParam () {echo "第一个参数为 $1 !"echo "第二个参数为 $2 !"echo "第十个参数为 $10 !"echo "第十个参数为 ${10} !"echo "第十一个参数为 ${11} !"echo "参数总数有 $# 个!"echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

输出结果:

 不难发现,echo "第十个参数为 $10 !"  第三行输出的值为10,为什么呢?不是应该为34吗,是因为$10被拆分为$1+0, 就是第一个参数1的值加上字符串0的拼接等于10,所以大家用的时候还是尽量注意加中括号给解释器区分一下区间。

参数区分给大家罗列一下~

参数处理说明
$#传递到脚本或函数的参数个数
$*以一个单字符串显示所有向脚本传递的参数
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与$*相同,但是使用时加引号,并在引号中返回每个参数
$-显示Shell使用的当前选项,与set命令功能相同
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误

三、脚本引用

和其他语言一样,Shell也可以引用外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。

Shell文件包含的语法格式如下:

. filename  # 注意点号(.)和文件名中间有一空格
或
source filename

下面我们直接举个栗子🌰~

先创建2个shell脚本文件。

function4.sh代码如下:

#!/bin/bash
work () {echo "第一个参数为 $1 !"echo "第二个参数为 $2 !"
}

function5.sh代码如下,还要赋予function5.sh这个脚本执行的权限chmod +x filename.sh:

#!/bin/bash
# 或者这么写 
# soure ./function4.sh
. ./function4.shwork 11 22 33 44 55

执行function5.sh结果:

四、输出命令

(1)echo就不讲啦

(2)printf

printf命令模仿C程序库(library)里的printf()程序。

printf 由 POSIX标准所定义,因此使用printf的脚本比使用echo移植性好。

printf使用引用文本或空格分隔的参数,可以在printf中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的printf不会像echo自动添加换行符,我们可以手动添加 \n

printf命令的语法:

printf format-string [arguments...]
  • format-string:为格式控制字符串
  • arguments:为参数列表
$echo "hello, shell"
hello, shell
$printf "hello,shell\n"
hello, shell

 

五、重定向

(1)标准输入输出 

一般情况下,每个Unix/Linux命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

我们直接来个栗子🌰更容易理解~

(2)输出重定向

 我输入ls的时候,显示很多文件,会把这个输出的内容重定向到默认的标准输出文件(stdout),

那同学们,我们可不可以把标准输出文件定义为我们自定义的一个文件呢?

当然可以,

ls 1>res.txt

那我们输入ls 1>res.txt的时候发现下面没有输出任何东西,为什么?

因为我们把输出内容从标准输出文件重定向到res.txt这个文件里面去了。

这个时候我们cat一下看看

还有一种情况,我们想ls aaa这个文件夹,但是没有这个aaa文件夹,怎么重定向?

 同样的道理~这个时候没有输出任何内容,因为被重定向在了response.txt文件里。

 这个时候我们cat一下这个response.txt试试看


 但是我们每次重定向一次,就会覆盖当前txt文件里面的内容,我们可以通过 << 往文件里追加内容

echo 666 >> response.txt 

(3)输入重定向

六、/dev/null文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null: 

command > /dev/null

/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容妈妈,那么什么也读取不到。但是 /dev/null文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。

如果希望屏蔽stdout 和stderr,可以这样写:

$ command > /dev/null 2>&1
$ command & /dev/null  # 简写

这里的2和>之间不可以有空格, 2>是一体的时候才表示错误输出。

七、shell展开

(1)简介

Shell接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell会展开词元里面的特殊字符,展开完成后才会调用相应的命令。

这种特殊字符的展开,称为shell展开(expansion)。其中有些用到通配符,又称为通配符展开(wildcard expansion)。Bash一共提供七种展开。

  • 大括号展开
  • 波浪线展开
  • 参数/变量展开
  • 算数展开
  • 子命令展开
  • 分词
  • 文件名展开

展开的顺序是:大括号展开、波浪展开、参数和变量展开、算数展开和子命令展开(以从左到右的方式完成),分词和文件名扩展。

Bash是先进行展开,再执行命令。因此,展开的结果是由Bash负责的,与所要执行的命令无关。命令本身并不存在参数扩展,收到什么参数就原样执行。

下面我们来举个栗子🌰~

 

 为什么我们输入 $name  他会输出liyifeng呢? 因为shell接收到用户输入的命令之后,会根据空格将用户的输入拆分,进行符号展开。

(2)大括号展开

大括号扩展 {...} 表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔。比如, {1,2,3}扩展成1 2 3

 注意1:有一个需要注意的地方是,大括号内部的逗号前后不能有空格。否则,大括号扩展会失效。 

注意2:逗号前面可以没有值, 表示扩展的第一项为空

 注意3:大括号还可以嵌套

 

注意4:大括号扩展有一个简写形式{start..end},表示扩展成一个连续序列。

还支持逆序

如果遇到无法理解的简写,大括号模式就会原样输出,不会扩展。 

还能补齐宽度,如果整数前面有前导0,将会强制每项具有相同的宽度,宽度不够会添加前导0。

  这种简写形式还可以使用第二个双点号( start..end..step ),用来指定扩展的步长。

 

(3) 波浪线展开

还可以这么写 cd ~/aa,就是进入主目录下面的aa文件夹

 

也可以这么写 cd ~zhanzhao,进入zhanzhao这个用户的家目录

 

还可以这么写 ~+,效果等同于 pwd 命令,显示当前所在的目录。

 每个变量的赋值都要检查紧跟在':'或第一个'='后面的未加引号的波浪前缀。在这些情况下,也会执行波浪展开。

 

 (4) 变量展开

4.1: 正常用法

Bash将美元符号 $ 开头的词元视为变量,将其扩展成变量值。

变量名除了放在美元符号后面,也可以放在 ${} 里面

name=wangyibo
echo $name
echo ${name}# 输出结果
wangyibo
wangyibo

还可以通过 ${!变量名} 进行间接扩展,它首先在 !变量名 部分展开成变量对应的值,然后将这个值当做变量名,在进行变量展开。

name=dengchao
n=name
echo ${!n}输出结果:
dengchao

 

4.2: 其他用法

1.如果parameter未设置或为空,则word的展开将被替换。否则,参数的值将被替换。

${parameter:-word}

栗子🌰(其实就是给个默认值的意思):

echo ${name:-word}
word

 2.如果parameter未设置或为空,则将word的展开部分赋给parameter。然后替换parameter的值。位置参数和特殊参数不能以这种方式赋值。

echo ${name:=word}

栗子🌰(其实就是给个默认赋值的意思):

echo ${name:=word}
word
echo $name
word

3.如果parameter未设置或为空,则word的展开(或word不存在时的展开消息)被写入标准错误,如果shell不是交互式的,则退出。

${parameter:?word}

栗子🌰:

echo ${aaa:?error}
-bash: aaa:errorecho ${aaa:?1223}
-bash: aaa:1223

 4.如果parameter未设置或为空,则不替换任何内容,否则替换word的展开。

${parameter:+word}

栗子🌰:

name=xinlan
echo ${name:+word}word

5.子字符串扩展。类似于python的切片,它获取长度为length的参数值的字符,从offset位置开始。如果省略了length,则它从offset指定的字符开始,一直扩展到值的末尾。

${parameter:offset}${parameter:offset:length}

 栗子🌰:

$ string=01234567890abcdefgh
$echo ${string:7}
7890abcdefgh$ echo ${string:7:0}$ echo ${string:7:2}
78

如果offset为负数,则该值将表示从结束开始的字符偏移量。也就是说 -1 表示倒数第一个,-2倒数第二个以此类推。请注意,负偏移量必须与冒号之间至少有一个空格隔开,以避免与":-"展开形式混淆。 

栗子🌰:

$ string=01234567890abcdefgh
$echo ${string: -7}
bcdefgh$ echo ${string: -7:0}$ echo ${string: -7:2}
bc

如果length的值为负数,则它被解释为从结束开始的字符偏移量, 展开结果为和offset之间的字符。

注意:如果是参数 @, 或者是下标为 @ 或 * 的索引数组时,length不能为负数, 否则会报错。

$ string=01234567890abcdefgh
$echo ${string:7:-2}
7890abcdef$ echo ${string: -7:-2}
bcdef

6. 扩展为名称以前缀开头的变量名

${!prefix*}${!prefix@}

 栗子🌰:

echo ${!na*}
na name

7.获取字符串参数的长度:

name="abcdef"
${#name}6

还有很多就不一一赘述了。。 

(5)子命令展开

命令替换允许命令的输出替换命令本身。

当命令被如下所示包围时,就会发生命令替换:

$(command)

或者

`command`

 

 

 

(6)算数展开

算数展开允许对算数表达式求值并替换结果。算数展开的格式为:

$(( expression ))

 表达式会被当作双引号内的表达式来处理,但是括号内的双引号不会被特别处理。表达式中的所有标记都要进行参数和变量展开、命令替换和引号删除。结果被视为要求值的算数表达式。算数展开可以嵌套。

(7)文件名展开(重点)

文件名展开主要是通过三个字符 ? *[ ]

7.1 ?字符

? 字符代表文件路径里面的任意单个字符,不包括空字符。比如, Data???匹配所有 Data 后面跟着三个字符的文件名。

 如果文件不存在,展开就不会发生。

7.2 * 字符

* 字符代表文件路径里面的任意数量的任意字符,包括零个字符

注意1:* 不会匹配隐藏文件(以 . 开头的文件),即 ls * 不会输出隐藏文件。如果要匹配隐藏文件,需要写成 .*

注意2:* 只匹配当前目录,不会匹配子目录,可以通过ls */*匹配子目录

ls *ls */*

 

7.3 [ ]字符 

# 显示所有隐藏文件
$ echo .*# 如果要匹配隐藏文件,同时要排除 . 和 .. 这2个特殊的隐藏文件,可以与方括号扩展结合使用
$ echo .[!.]*

注意,如果文件不存在,展开不会发生,如果文件存在就会原样输出。

方括号扩展的形式是 [...],只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。括号之中的任意一个字符。比如, [aeiou]可以匹配五个元音子母中的任意一个。

 

 

 (8)量词语法

量词语法用来控制模式匹配的次数。它只有在 Bash 的 extglob 参数打开的情况下才能使用,不过一般是默认打开的。下面的命令可以查询。

$ shopt extglob
extglob      on

如果 extglob 参数是关闭的, 可以用下面的命令打开。

$ shopt -s extglob

量词语法有下面几个:

  • ?(pattern-list) : 模式匹配零次或一次
  • *(pattern-list) : 模式匹配零次或多次
  • +(pattern-list) : 模式匹配一次或多次
  • @(pattern-list) : 只匹配一次模式
  • !(pattern-list) : 匹配给定模式以外

举栗子🌰~ 

# ?(.)匹配零个或一个点
$ ls abc?(.)txt
abctxt  abc.txt
# ?(def)匹配零次或一个
$ ls abc?(def)
abc abcdef
# @(.txt|.php)匹配文件有且只有一个 .txt 或 .php后缀名
$ ls abc@(.txt|.php)
abc.php abc.txt
# +(.txt)匹配文件有一个或多个.txt后缀名
$ ls abc+(.txt)
abc.txt abc.txt.txt
# !(b)表示匹配单个字母b以外的任意内容,所以除了ab.txt以外,其他文件名都能匹配
$ ls a!(b).txt
a.txt abb.txt ac.txt

量词语法也属于文件名扩展,如果不存在可匹配的文件,就会原样输出

# 没有 abc 开头的文件
$ ls abc?(def)
ls:无法访问'abc?(def)':没有那个文件或目录

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

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

相关文章

软件项目管理:外包 outsourcing、采购 procurement、合同 contracts

文章目录外包不同类型为什么选择外包好处坏处采购 procurementplanning 阶段-弄清需求 & 市场 / 评估风险Source 阶段-确定供应商具体过程RFxState of Work (SOW)评估步骤 Evaluation processManage 阶段Contract 合同定义种类固定价格合同适用场景&#xff08;保守&#x…

稀疏矩阵的压缩存储

目录 稀疏矩阵的定义 稀疏矩阵的转置 代码实现 运行结果 稀疏矩阵的定义 假设在 m * n 的矩阵中&#xff0c;有 t 个元素不为零&#xff0c;且 t<<m*n&#xff0c;则称此矩阵为稀疏矩阵。按照常规的存储方法&#xff0c;稀疏矩阵很浪费内存空间&#xff0c;所以采取…

学习梦想家CMS内容管理系统-环境启动

gitee官网中项目的地址&#xff1a;首先准备里面提到的工具其中JDK8和MySQL5.7我们已经有了&#xff0c;现在需要准备另外的工具。 Spring Tool Suite 4&#xff08;STS&#xff09; 安装过程在《1-1-Spring Tool Suite 4&#xff08;STS&#xff09;的下载安装》 Redis 安装…

数字孪生在电网系统开发建设,如何选择可视化平台?

随着新能源发展规模持续增大&#xff0c;电网作为能源转换利用和输送配置的枢纽平台&#xff0c;其功能、结构和形态发生了深刻变化。同时&#xff0c;随着现代计算机技术发展&#xff0c;数字孪生成为电网向数字化转型、提高电网调度运行决策的准确性与实时性提供关键技术支撑…

初识数据库-MySQL数据库

文章目录数据库数据库的相关概念常见的关系型数据库管理系统MySQL数据库MySQL目录结构MySQL数据模型数据库 数据库的相关概念 数据库 存储数据的仓库&#xff0c;数据是有组织的进行存储英文&#xff1a; DataBase,简称 DB 数据库管理系统 管理数据库的大型软件英文&#xff…

震撼上新丨云和恩墨新一代数据库存储 zStorage 和数据库一体机 zData X 即将发布...

存储&#xff0c;在一定程度上可以称为数据库存储&#xff0c;存储与数据库的发展总是相生相随。技术上&#xff0c;数据库对高 I/O 频率、低时延、高可靠性的追求一直是存储更快、更高、更强需求的来源。商业上&#xff0c;两家影响世界的公司 Oracle 和 EMC 几乎同时起步于 1…

使用element ui的el-upload组件上传图片,记录一下

使用element ui的el-upload组件上传图片 效果预览 下面是实现效果,接口方面是把有两个接口,一个接口上传图片,传参是图片和路径,返回值是路径。另一个接口是上传表单内容(用户,地址,照片),照片是传一个路径。具体实现 html <el-form-item label="上传照片"…

第二十一章 函数递归

一、函数递归调用介绍 函数不仅可以嵌套定义,还可以嵌套调用,即在调用一个函数的过程中,函数内部又调用另一个函数,而函数的递归调用指的是在调用一个函数的过程中又直接或间接地调用该函数本身。例如在调用f1的过程中,又调用f1,这就是直接调用函数f1本身def f1():print(…

springboot(三)

视频链接&#xff1a;https://www.bilibili.com/video/BV1XQ4y1m7ex/?vd_source9545770e4a2968c05878ffac8589ec6c 视频选集&#xff1a;P58— P92 文章目录1.接口架构风格-RESTful1.1 认识REST1.2 RESTful的注解1.2.1 PathVariable1.2.2 PostMapping1.2.3 DeleteMapping1.2.4…

分布式缓存

本文介绍关于缓存的常用设计模式。以及如何保证缓存的一致性进行分类讨论。 还会介绍关于缓存失效的常见问题&#xff0c;以及针对缓存失效的解决方法。 在高并发的环境下&#xff0c;比如春节抢票大战&#xff0c;一到放票的时间节点&#xff0c;分分钟大量用户以及黄牛的各种…

魔改xxl-job,彻底告别手动配置任务!

xxl-job是一款非常优秀的任务调度中间件,轻量级、使用简单,但是苦于手动注册任务久矣,今天就来魔改一下,实现任务的自动注册!原创:微信公众号 码农参上,欢迎分享,转载请保留出处。哈喽大家好啊,我是Hydra。 xxl-job是一款非常优秀的任务调度中间件,轻量级、使用简单、…

12个小细节让普源示波器使用更加高效(上)

俗话说细节决定成败&#xff0c;示波器作为电子测量的第一工具&#xff0c;虽然使用简单&#xff0c;但并不是每个人都能注意到细节。运用好细节&#xff0c;可以使你的示波器使用更加的便捷。以下由安泰测试带来普源示波器测量相关的12个小细节可作为示波器常识快速自检的小文…

Spring Boot(4):@Import注解和@Conditional注解

说明&#xff1a;基于atguigu学习笔记。 在了解spring boot自动配置原理前&#xff0c;再来了解下两个注解Import注解和Conditional注解。 Import Import注解主要用于导入某些特殊的Bean&#xff0c;这些特殊的Bean和Bean Definitaion 有关。 主要用于导入Configuration 类…

Python实现桌面挂件,做一只可爱的桌面宠物~

文章目录嗨嗨&#xff0c;大家好 ~ 我是小圆相关文件开发工具相关模块&#xff1a;环境搭建安装原理简介1.初始化一个窗口组件&#xff1a;效果2.设置一下窗口的属性&#xff1a;随机导入一张图片&#xff0c;看效果随机导入一个宠物的所有图片的函数代码3.宠物随机出现在桌面上…

服务端渲染的探索与实践

服务端渲染(SSR)近两年炒得很火热,相信各位同学对这个名词多少有所耳闻。本节我们将围绕“是什么”(服务端渲染的运行机制)、“为什么”(服务端渲染解决了什么性能问题 )、“怎么做”(服务端渲染的应用实例与使用场景)这三个点,对服务端渲染进行探索。 服务端渲染是一…

GOM引擎登录器的研究,逆向技术在这款GOM20151108引擎上是一个大舞台

最近遇到一个逆向类课题&#xff0c;是关于GOM20151108版本对应登录器研究。刚接触传奇的时候是2002年&#xff0c;那时候网吧玩SF&#xff0c;都是手动用IP直接连接&#xff0c;当时的一款 联创传奇 很好玩&#xff0c;有传送戒子&#xff0c;木域戒指&#xff0c;土域戒指&am…

不会 Vue,但不影响我学 diff 算法

前言 现在社会各行各业大都面临着寒冬&#xff0c;互联网行业最近还出现了裁员潮&#xff0c;导致前端是越来越卷&#xff0c;普通学校的应届生不仅要跟985、211毕业的学生以及研究生进行竞争&#xff0c;甚至还需要和最近刚被裁的、有了几年工作经验的程序员竞争&#xff0c;…

page.json

uni-app需要给page.json文件需要进行配置路由,否则会不报错,也跳转不过去

【数模/启发式算法】蚁群算法

文章目录简介符号说明核心思想流程图文章使用到的测试函数基本步骤蚁群算法代码简介 蚁群算法是一种用来寻找优化路径的概率型算法。它由Marco Dorigo于1992年在他的博士论文中提出&#xff0c;其灵感来源于蚂蚁在寻找食物过程中发现路径的行为。 这种算法具有分布计算、信息正…

Arduino播放声音

玩软件有点虚无&#xff0c;没有实际东西&#xff0c;所以接下来要体验下硬件与软件结合。 1 Arduino Arduino是一种包含硬件&#xff08;各种型号的Arduino板&#xff09;和软件&#xff08;Arduino IDE&#xff09;的开源电子平台。硬件部分是可以用来做电路连接的Arduino电…