赞
踩
思维导图结构:
shell是什么呢?其实是我们一直在用的,所有的命令都是通过shell去实现的,看来自菜鸟教程的介绍:
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Ken Thompson 的 sh 是第一种 Unix Shell,Windows Explorer 是一个典型的图形界面 Shell。
它所说的界面,可能就是我们一直用的黑框框吧,是不是一说界面会想到图形化界面,还在纳闷呢!哈哈
大家已经写过一个脚本了hello world,在之前的章节中,我们已经写过一个小小的脚本,万能的hello world;
菜鸟教程对这里部分基础写的非常好,这里大量参考菜鸟教程Linux-shell部分加上自己的理解,帮大家进行一遍梳理;
这里我们再重新认识下,新建一个文件为hello.sh,使用vim在里面编辑:
#!/bin/bash #! 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行
echo "Hello World !" #命令用于向窗口输出文本。
当然了,这个时候还不能运行./hello.sh
试一下,提示权限不够,是因为文件并没有执行权限,我们需要给文件添加执行权限,chmod +x hello.sh
,再次执行,成功!
[root@localhost test]# vim hello.sh
[root@localhost test]# ./hello.sh
-bash: ./hello.sh: 权限不够
[root@localhost test]# chmod +x hello.sh
[root@localhost test]# ls
helloNos.txt hello.sh helloS.txt hello.txt
[root@localhost test]# ./hello.sh
hello,world
[root@localhost test]#
注意,一定要写成 ./hello.sh,而不是 hello.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 hello.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./hello.sh 告诉系统说,就在当前目录找。
所以知道为什么执行命令需要加./
了吧
可能还有疑惑,后缀名就一定.sh是这样吗?不是的,我们来试一下,我修改了文件的名字,为hello.t再次执行还是没有问题,因为这里不像C、java、python需要固定的后缀名.c .java .py 文件名是什么都没有任何问题,.sh后缀是一种很好的规范,到时候你和别人都可以知道这是一个shell脚本文件:
[root@localhost test]# mv hello.sh hello.t
[root@localhost test]# ls
helloNos.txt helloS.txt hello.t hello.txt
[root@localhost test]# ./hello.t
hello,world
[root@localhost test]#
变量定义:
定义变量时,变量名不加美元符号($,我们使用变量时需要),如:
your_name=“runoob.com”
注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:
有效的 Shell 变量名示例如下:
RUNOOB
LD_LIBRARY_PATH
_var
var2
无效的变量命名:
?var=123
user*name=runoob
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="qinjx"
echo $your_name
echo ${your_name}
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
下面的例子尝试更改只读变量,结果报错:
#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com"
运行脚本,结果如下:
/bin/sh: NAME: This variable is read only.
使用 unset 命令可以删除变量。语法:
unset variable_name
变量被删除后不能再次使用。unset 命令不能删除只读变量。
#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
运行shell时,会同时存在三种变量:
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号
单引号字符串的限制:
双引号
双引号的优点:
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
输出结果为:
hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !
string="abcd"
echo ${#string} # 输出 4
echo ${#string[0]} # 输出 4
变量为数组时,KaTeX parse error: Expected '}', got '#' at position 2: {#̲string}** 等价于 *…{#string[0]}:
以下实例从字符串第 2 个字符开始截取 4 个字符:
string="runoob is a great site"
echo ${string:1:4} # 输出 unoo
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。
bash支持一维数组(不支持多维数组),并且没有限定数组的大小。
类似于 C 语言,数组元素的下标由 0 开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于 0。
在 Shell 中,用括号来表示数组,数组元素用"空格"符号分割开。定义数组的一般形式为:
数组名=(值1 值2 ... 值n)
例如:
array_name=(value0 value1 value2 value3)
或者
array_name=(
value0
value1
value2
value3
)
还可以单独定义数组的各个分量:
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
注意:可以不使用连续的下标,而且下标的范围没有限制。
读取数组元素值的一般格式是:
${数组名[下标]}
例如:
valuen=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
获取数组长度的方法与获取字符串长度的方法相同,例如:
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
以 # 开头的行就是注释,会被解释器忽略。
通过每一行加一个 # 号设置多行注释,像这样:
#--------------------------------------------
# 这是一个注释
多行注释还可以使用以下格式:
:<<EOF
注释内容...
注释内容...
注释内容...
EOF
EOF 也可以使用其他符号:
:<<'
注释内容...
注释内容...
注释内容...
'
:<<!
注释内容...
注释内容...
注释内容...
!
我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n。n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……
以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
为脚本设置可执行权限,并执行脚本,输出结果如下所示:
$ chmod +x test.sh
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
另外,还有几个特殊字符用来处理参数:
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数。 如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与 ∗ 相 同 , 但 是 使 用 时 加 引 号 , 并 在 引 号 中 返 回 每 个 参 数 。 如 " *相同,但是使用时加引号,并在引号中返回每个参数。 如" ∗相同,但是使用时加引号,并在引号中返回每个参数。如"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2"…"n” 的形式输出所有参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
不做过多赘述了,这里大家直接去参考菜鸟教程吧!
看我列出的知识点:
echo我们已经使用了很多了,printf也差不多,大家看一眼即可;
来吧给大家打开一个,传送门
linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。
shell中函数的定义格式如下:
定义格式:
[ function ] funname [()]
{
action;
#代码体
[return int;] #返回值
}
说明:
#!/bin/bash
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
输出结果:
-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
下面定义一个带有return语句的函数:
#!/bin/bash
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum #read读取输入的数值
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $?"
输出类似下面:
这个函数会对输入的两个数字进行相加运算...
输入第一个数字:
1
输入第二个数字:
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3
函数返回值在调用该函数后通过 $? 来获得。
在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
输出结果:
第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
注意, 10 不 能 获 取 第 十 个 参 数 , 获 取 第 十 个 参 数 需 要 10 不能获取第十个参数,获取第十个参数需要 10不能获取第十个参数,获取第十个参数需要{10}。当n>=10时,需要使用${n}来获取参数。
另外,还有几个特殊字符用来处理参数:
参数处理 | 说明 |
---|---|
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示Shell使用的当前选项,与set命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
函数与命令的执行结果可以作为条件语句使用。
要注意的是,和 C 语言不同,shell 语言中 0 代表 true,0 以外的值代表 false。
作业:
y猜的比x大,反馈猜大了,相反,反馈猜小了,x=y时,游戏结束,恭喜答对;
什么是IO重定向呢?
我们拆开理解,IO就是输入和输出,我们知道我们的程序都是在对数据的输入输出(传递),那什么是重定向呢,就是改变输入输出的方向,我们知道默认模式下,输入输出都是在终端,你对终端输入,程序对终端输出,但有时候我们又不想输入输出重定向,比如:日志和错误,都是应该保存文件中,供我们找出问题,查找问题,这时候就需要输入输出重定向了;
很简单:只需要知道<、>、 >&、<&、>>、<<
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file。 |
command < file | 将输入重定向到 file。 |
command >> file | 将输出以追加的方式重定向到 file。 |
n > file | 将文件描述符为 n 的文件重定向到 file。 |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file。 |
n >& m | 将输出文件 m 和 n 合并。 |
n <& m | 将输入文件 m 和 n 合并。 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入。 |
需要注意的是文件描述符 0 通常是标准输入(STDIN),1 是标准输出(STDOUT),2 是标准错误输出(STDERR)。
这里做一个小案例即可:
我里有个程序,需要输入日志到执行位置,以便后期维护和查看:
程序代码:
#!/bin/bash
echo '程序执行成功,没有bug'
需要输入到相同目录下的log文件中:
#新建文件和程序
[root@localhost ~]# cd /home/test
[root@localhost test]# ls
helloNos.txt helloS.txt hello.t hello.txt
[root@localhost test]# vim logTest.sh
[root@localhost test]# ls
helloNos.txt helloS.txt hello.t hello.txt logTest.sh
[root@localhost test]# cat logTest.sh
#!/bin/bash
echo '程序执行成功,没有bug'
[root@localhost test]# chmod +x logTest.sh
#执行程序没有问题
[root@localhost test]# ./logTest.sh
程序执行成功,没有bug
查看结果
#将程序执行日志放入log中,我们可以看到,我们程序执行产生的日志都会在log中,供我们维护和查看
[root@localhost test]# ./logTest.sh > log
[root@localhost test]# ls
helloNos.txt helloS.txt hello.t hello.txt log logTest.sh
[root@localhost test]# cat log
程序执行成功,没有bug
[root@localhost test]#
那么>>
就是想文件末尾追加,以及>&
和<<
不难理解了哈!
希望篇文章对大家有帮助,可以用来参考!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。