当前位置:   article > 正文

Linux-Shell学习笔记教程,快速学习_linux shell 菜鸟教程

linux shell 菜鸟教程

Linux-Shell

思维导图结构:
在这里插入图片描述

介绍

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 !"	     #命令用于向窗口输出文本。
  • 1
  • 2

当然了,这个时候还不能运行./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]# 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注意,一定要写成 ./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]# 

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Shell语法

变量

变量定义:

定义变量时,变量名不加美元符号($,我们使用变量时需要),如:

your_name=“runoob.com”

注意,变量名和等号之间不能有空格,这可能和你熟悉的所有编程语言都不一样。同时,变量名的命名须遵循如下规则:

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
  • 中间不能有空格,可以使用下划线 _
  • 不能使用标点符号。
  • 不能使用bash里的关键字(可用help命令查看保留关键字)。

有效的 Shell 变量名示例如下:

RUNOOB
LD_LIBRARY_PATH
_var
var2
  • 1
  • 2
  • 3
  • 4

无效的变量命名:

?var=123
user*name=runoob
  • 1
  • 2
使用变量

使用一个定义过的变量,只要在变量名前面加美元符号即可,如:

实例
your_name="qinjx"
echo $your_name
echo ${your_name}
  • 1
  • 2
  • 3
只读变量

使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。

下面的例子尝试更改只读变量,结果报错:

实例
#!/bin/bash

myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com"
  • 1
  • 2
  • 3
  • 4
  • 5

运行脚本,结果如下:

/bin/sh: NAME: This variable is read only.
  • 1
删除变量

使用 unset 命令可以删除变量。语法:

unset variable_name
  • 1

变量被删除后不能再次使用。unset 命令不能删除只读变量。

实例
#!/bin/sh

myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl
  • 1
  • 2
  • 3
  • 4
  • 5
变量类型

运行shell时,会同时存在三种变量:

  • 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
  • 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
  • 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

输出结果为:

hello, runoob ! hello, runoob !
hello, runoob ! hello, ${your_name} !
  • 1
  • 2
获取字符串长度
实例
string="abcd"
echo ${#string}   # 输出 4

echo ${#string[0]}   # 输出 4
  • 1
  • 2
  • 3
  • 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
  • 1
  • 2
查找子字符串

查找字符 io 的位置(哪个字母先出现就计算哪个):

实例
string="runoob is a great site"
echo `expr index "$string" io`  # 输出 4
注意: 以上脚本中 ` 是反引号,而不是单引号 ',不要看错了哦。
  • 1
  • 2
  • 3

Shell 数组

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
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

注意:可以不使用连续的下标,而且下标的范围没有限制。

读取数组

读取数组元素值的一般格式是:

${数组名[下标]}
  • 1

例如:

valuen=${array_name[n]}
  • 1

使用 @ 符号可以获取数组中的所有元素,例如:

echo ${array_name[@]}
  • 1
获取数组的长度

获取数组长度的方法与获取字符串长度的方法相同,例如:

实例
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
lengthn=${#array_name[n]}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

shell注释

单行注释

# 开头的行就是注释,会被解释器忽略。

通过每一行加一个 # 号设置多行注释,像这样:

#--------------------------------------------
# 这是一个注释
  • 1
  • 2

多行注释

多行注释还可以使用以下格式:

:<<EOF
注释内容...
注释内容...
注释内容...
EOF
  • 1
  • 2
  • 3
  • 4
  • 5
实例

EOF 也可以使用其他符号:

:<<'
注释内容...
注释内容...
注释内容...
'

:<<!
注释内容...
注释内容...
注释内容...
!
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

Shell运算

Shell 传递参数

我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$nn 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推……

实例

以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径):

实例

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com

echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

为脚本设置可执行权限,并执行脚本,输出结果如下所示:

$ chmod +x test.sh 
$ ./test.sh 1 2 3
Shell 传递参数实例!
执行的文件名:./test.sh
第一个参数为:1
第二个参数为:2
第三个参数为:3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

另外,还有几个特殊字符用来处理参数:

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。 如"$*“用「”」括起来的情况、以"$1 $2 … $n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@ ∗ 相 同 , 但 是 使 用 时 加 引 号 , 并 在 引 号 中 返 回 每 个 参 数 。 如 " *相同,但是使用时加引号,并在引号中返回每个参数。 如" 使"@“用「”」括起来的情况、以"$1" “ 2 " … " 2" … " 2""n” 的形式输出所有参数。
$-显示Shell使用的当前选项,与set命令功能相同。
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

逻辑运算

不做过多赘述了,这里大家直接去参考菜鸟教程吧!

看我列出的知识点:

  1. bool
  2. test
  3. if···then
  4. while
  5. for
  6. until
  7. case … esac
  8. break
  9. continue
  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

echo我们已经使用了很多了,printf也差不多,大家看一眼即可;

来吧给大家打开一个,传送门

Shell函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

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

定义格式:

[ function ] funname [()]
{
    action;
	#代码体
    [return int;]  #返回值
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

说明

  • 1、可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 2、参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return后跟数值n(0-255)

例子

#!/bin/bash
demoFun(){
    echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

输出结果:

-----函数开始执行-----
这是我的第一个 shell 函数!
-----函数执行完毕-----
  • 1
  • 2
  • 3

下面定义一个带有return语句的函数:

#!/bin/bash
funWithReturn(){
    echo "这个函数会对输入的两个数字进行相加运算..."
    echo "输入第一个数字: "
    read aNum			#read读取输入的数值
    echo "输入第二个数字: "
    read anotherNum
    echo "两个数字分别为 $aNum$anotherNum !"
    return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $?"
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

输出类似下面:

这个函数会对输入的两个数字进行相加运算...
输入第一个数字: 
1
输入第二个数字: 
2
两个数字分别为 1 和 2 !
输入的两个数字之和为 3
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

函数返回值在调用该函数后通过 $? 来获得。

函数参数

在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
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果:

第一个参数为 1 !
第二个参数为 2 !
第十个参数为 10 !
第十个参数为 34 !
第十一个参数为 73 !
参数总数有 11 个!
作为一个字符串输出所有参数 1 2 3 4 5 6 7 8 9 34 73 !
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意 10 不 能 获 取 第 十 个 参 数 , 获 取 第 十 个 参 数 需 要 10 不能获取第十个参数,获取第十个参数需要 10{10}。当n>=10时,需要使用${n}来获取参数。

另外,还有几个特殊字符用来处理参数:

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

函数与命令的执行结果可以作为条件语句使用。

要注意的是,和 C 语言不同,shell 语言中 0 代表 true,0 以外的值代表 false。

实践小程序

作业

  1. 完成一个二人猜年龄游戏,程序需要询问第一个人的年龄(x)是多少,然后再询问第二个人猜测第一个人的年龄(y)是多少,

y猜的比x大,反馈猜大了,相反,反馈猜小了,x=y时,游戏结束,恭喜答对;

  1. 大家还可以写下算法小程序,归并排序、快速排序、冒泡排序······

IO重定向

什么是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'
  • 1
  • 2

需要输入到相同目录下的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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

查看结果

#将程序执行日志放入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]# 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

那么>>就是想文件末尾追加,以及>&<<不难理解了哈!

小结

希望篇文章对大家有帮助,可以用来参考!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/676230
推荐阅读
相关标签
  

闽ICP备14008679号