shell编程
shell
什么是shell?
shell就是基于用户和操作系统内核之间的一个应用程序,可以让用户更简单高效安全地使用和操作linux内核。
shell是像javaScript,python一样,都是解释性语言(脚本语言),一边解释一边执行,不会生成任何可执行文件。
shell命令
shell命令分为内置命令和外部命令,一个 Shell 内置命令就是一个shell内部的函数,一个外部命令就是一个应用程序。内置命令是常驻与内存中的,而外部命令由于是一个应用程序,使用外部命令需要启动一个进程,所以相对于内置命令来说,执行外部命令相对内置命令耗时上较久。
其中$PATH 变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。
可以使用 type 来确定一个命令是否是内建命令:
[atguigu@hadoop01 bin]$ type ifconfig
ifconfig 是 /usr/sbin/ifconfig
[atguigu@hadoop01 bin]$ type cd
cd 是 shell 内嵌
shell命令基本格式:commend [选项] [参数]
其中[选项]中也可以携带参数。
例如:read -n 1 sex
命令用来读取一个字符并赋值给 sex 变量,其中-n 是 read 命令的选项,1 是-n 选项的参数,sex 是 read 命令的参数。
Shell 命令的选项和参数在本质:不管是内置命令还是外部命令,它后面附带的数据最终都以参数的形式传递给了函数。实现一个命令的一项重要工作就是解析传递给函数的参数。
执行shell脚本(多种方式)
在新进程中执行
方式1:将 Shell 脚本作为程序运行
Shell 脚本也是一种解释执行的程序,可以在终端直接调用(需要使用 chmod 命令给 Shell 脚本加上执行权限),如下所示:
[atguigu@hadoop01 bin]$ ls
check.sh getsum getsum.c test.sh
[atguigu@hadoop01 bin]$ chmod +x ./check.sh #给脚本添加执行权限
[atguigu@hadoop01 bin]$ ./check.sh #执行脚本文件
4600 #当前pid
方式2:将 Shell 脚本作为参数传递给 Bash 解释器
[atguigu@hadoop01 bin]$ /bin/bash ./check.sh
4606
[atguigu@hadoop01 bin]$ bash ./check.sh #bash是一个外部命令,本质与/bin/bash一样
4607
无论是方式1还是方式2,都是需要在执行脚本文件前面添加./
来保证是执行当前目录下的,否则linux会去$PATH
变量中去寻找,如果你配了可执行程序所在文件的环境变量则可以省./
。
在当前进程中执行
使用source命令,source 是 Shell 内置命令的一种,它会读取脚本文件中的代码,并依次执行所有语句。 你也可以理解为,source 命令会强制执行脚本文件中的全部命令,而忽略脚本文件的权限。
# source命令格式
source filename #方式1
. filename #方式2
[atguigu@hadoop01 bin]$ echo $$ #输入当前进程
4574
[atguigu@hadoop01 bin]$ source check.sh #执行脚本文件
4574
[atguigu@hadoop01 bin]$ . check.sh #执行脚本文件
4574
[atguigu@hadoop01 bin]$ echo $$ #输入当前进程
4574
shell配置文件的加载
无论是否是交互式,是否是登录式,Bash Shell 在启动时总要配置其运行环境,例如初始化环境变量、设置命令提示符、指定系统命令 路径等。这个过程是通过加载一系列配置文件完成的,这些配置文件其实就是 Shell 脚本文件。
与 Bash Shell 有关的配置文件主要有 /etc/profile、~/.bash_profile、 ~/.bash_login、 ~/.profile、 ~/.bashrc、/etc/bashrc、 /etc/profile.d/*.sh,不同的启动方式会加载不同的配置文件。
登陆式
首先会先读取和执行/etc/profile
,这是所有用户的全局配置文件,其中/etc/profile还会嵌套加载 /etc/profile.d/*.sh
,然后再会到用户主目录中寻找~/.bash_profile ,~/.bash_login, ~/.profile,它们都是用户个人的配置文件。其中执行的优先级从高到低排列 ~/.bash_profile
>~/.bash_login
>~/.profile
,只会执行其中的一个。其中用户个人的配置文件也会嵌套加载~/.bashrc
配置文件。
所以加载顺序是先全局配置后再用户个人配置。
非登陆式
如果以非登录的方式启动 Shell,那么就不会读取以上所说的配置文件,而是直接读取 ~/.bashrc
。 ~/.bashrc 文件还会嵌套加载 /etc/bashrc
。
总结:
profile 类配置文件只在用户登录 Shell 时会被加载执行;而 bashrc 类配置文件除在用户登录 Shell 时会被加载执行之外,每当用户打开新的 Shell 或者子 Shell 时,都会被加载执行。通过修改这些配置文件,就可以指定用户在登录 Shell 时自动执行某些操作。相关链接参考:https://blog.csdn.net/xiaobinhxb/article/details/126318016
shell编程
变量
1. 变量中单引号和双引号的区别:
以单引号' '包围变量的值时,单引号里面是什么就输出什么,即使内容中有变量和命令(命令需要反引起来)也会把它们原样输出。这 种方式比较适合定义显示纯字符串的情况,即不希望解析变量、命令等的场景。
以双引号" "包围变量的值时,输出时会先解析里面的变量和命令,而不是把双引号中的变量名和命令原样输出。这种方式比较适合字符 串中附带有变量和命令并且想将其解析后再输出的变量定义。
如果变量的内容是数字,那么可以不加引号;如果真的需要原样输出就加单引号;其他没有特别要求的字符串等最好都加上双引号,定义变量时加双引号是最常见的使用场景。
-
将命令的结果赋值给变量
variable=$(command) variable=`{command}` # 注意这是反引号,与单引号容易混淆,建议使用上面的赋值方式
实例:
[atguigu@hadoop01 bin]$ log=$(cat log.txt) [atguigu@hadoop01 bin]$ echo $log 将命令的结果赋值给变量 [atguigu@hadoop01 bin]$ cat log.txt 将命令的结果赋值给变量
-
只读变量(readonly)
-
删除变量(unset) ,无法删除只读变量
变量的作用域
-
局部变量,只在函数内部生效,要加上关键字local,否则默认为全局变量,在函数外部也生效,在整个shell进程中也生效。
-
全局变量,在整个当前shell进程中都生效,打开一个命令行窗口就是一个shell进程,只在当前shell进程定义的变量都生效,并且是不同的shell脚本文件也是能读和取的。
-
环境变量,只存在于父子进程之间,使用关键字export将variable传递给子进程,并且只能父传给子,不能子传给父。如果父进程被关闭,则子进程获取的值也无法生效。
以上变量最大作用范围也就只能在父进程和子进程之间了,如果我们想要所用的shell进程都共享同一个变量,那么只有一个办法就是在shell初始化配置文件中进行变量的初始化赋值等操作,这样所有shell进程都能使用到一个变量了。
位置参数
格式:${1/2/3....n}来表示第几个参数
-
给函数传位置参数
#!/bin/bash #定义函数 function func(){ echo "language: ${1}" echo "name: ${2}" } #调用函数 chinese赋值到${1} lixuwei赋值到${2} func chinese lixuwei
然后执行该脚本文件:
[atguigu@hadoop01 bin]$ bash ./test.sh language: chinese name: lixuwei
-
给脚本文件传递位置参数
#!/bin/bash echo "language: ${1}" echo "name: ${2}"
执行脚本文件时传递参数:
[atguigu@hadoop01 bin]$ bash ./test.sh chinese lixuwei language: chinese name: lixuwei
shell中的特殊变量
例如上面提到的位置参数,就是shell编程中的其中一个特殊变量,还有其他的如下:
特殊变量 | 含义 |
---|---|
${n}(n>=1) | 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是 $1,第二个参数是 $2。 |
$ | 当前脚本的文件名 |
$# | 传递给脚本或函数的参数个数 |
$@ | 传递给脚本或函数的所有参数。 |
$* | 传递给脚本或函数的所有参数。 |
$? | 上个命令的退出状态,或函数的返回值 |
$$ | 当前进程的pid |
$@
和$*
的区别:
当 $* 和 $@ 不被双引号" "包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。 但是当它们被双引号" "包含时,就会有区别了:
"$*"
会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。
"$@"
仍然将每个参数都看作一份数据,彼此之间是独立的。
$?
获取函数返回值或者上个命令的退出状态
-
获取函数返回值
#!/bin/bash function add(){ return $(expr $1 + $2) } add 50 100 result=$? echo $result
获取函数返回值赋值到一个变量然后进行输出
-
获取上一个命令的退出状态
所谓退出状态,就是上一个命令执行后的返回结果。退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1, 这和 C 语言的 main() 函数是类似的。
#!/bin/bash if [ "$1" == 100 ] then exit 0 #参数正确,退出状态为 0 else exit 1 #参数错误,退出状态 1 fi
输入不同数字查看退出状态:
[atguigu@hadoop01 bin]$ bash ./test.sh 100 [atguigu@hadoop01 bin]$ echo $? 0 [atguigu@hadoop01 bin]$ bash ./test.sh -100 [atguigu@hadoop01 bin]$ echo $? 1
-
shell中的内置命令
$PATH 变量包含的目录中几乎聚集了系统中绝大多数的可执行命令,它们都是外部命令。
通常来说,内建命令会比外部命令执行得更快,执行外部命令时不但会触发磁盘 I/O,还需要 fork 出一个单独的进程来执行,执行完成后再退出。而执行内建命令相当于调用当前 Shell 进程的一个函数。
常用的几个内置命令有echo,read,exit,declare等,不会就去百度或者文档查找使用说明即可。这里我就不总结了,详细的可以去看c语言中文网哈。
本文作者:sunshineTv
本文链接:https://www.cnblogs.com/sunshineTv/p/17460116.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步