shell基础学习笔记

一、 shell脚本介绍

什么是shell命令?

Shell 和 GUI 一样是用户和操作系统之间的接口。

Shell 作为一种用户接口,它实际上是一个能够解释和分析用户键盘输入,执行输入中的命令,然后返回结果的一个解释程序。

$ ls
$ cd
$ pwd

什么是shell脚本

一系列的shell命令的集合, 还可以加入一些逻辑操作(if else for) 将这些命令放入一个文件中.

  • 是一个文件
  • 有n个shell命令
  • 可以加入逻辑
  • 需要在linux的终端中执行
# 举例 test.sh
ls       # 多条shell命令
pwd
if [ xxx ]
	cd ..

shell脚本的基本格式

  • 命名格式

    • 一般命名规则 : xxxxx.sh (建议以.sh为后缀命名)
  • 书写格式

    # test.sh #是shell脚本中的注释
    # 第一行指定解析shell脚本的时候使用的命令解析器,如果忘了了写, 使用默认的命令解析器 /bin/sh
    #!/bin/bash  # 指定命令解析器 /bin/sh也可以 bash是在sh的基础上开发的
    # 一系列的shell命令
    ls
    pwd
    cp 
    rm
    
  • shell脚本的执行

    # shell脚本编写完成之后, 必须添加执行权限
    chmod u+x xxx.sh  # u+x u是文件所有者,x是执行权限
    # 执行shell脚本
    ./xxx.sh 或者 sh test.sh
    

二、shell变量

命名规则

  • 和其他语言变量命名规则类似,注意不能有bash关键字

    • 字母,数字,下划线组成,字母区分大小写
    • 首个字符必须是字母
    • 不能使用bash里的关键字(help命令查看保留关键字)。

普通变量(本地变量)

# 定义变量, 定义完成, 必须要赋值, =前后不能有空格
# 普通变量只能在当前进程中使用
temp=666

# 普通变量取值
value=123	# 默认以字符串处理
value1 = "123 456"
echo $value
# 如何取变量的值:
 - $变量名
 - ${变量名}
两句效果一样,均为输出变量的值。变量名外面的花括号是可选的,加花括号是为了帮助解释器识别变量的边界。

在这里插入图片描述

环境变量

# 可以理解问全局变量, 在当前操作系统中可以全局访问
# 分类
	- 系统自带的(使用env命令查看)
		- PWD
		- SHELL
		- PATH
		- HOME
	- 用户自定义的
		- 将普通变量提升为系统级别的环境变量
		GOPATH=/home/gtt/go/src # 定义一个普通环境变量
		set GOPATH=/home/gtt/go/src # 系统环境变量
		export GOPATH=/home/gtt/go/src
		~/.bashrc # 刷新环境变量

位置变量

位置变量顾名思义就是和位置有关的变量:

  • $0: 执行的脚本文件的名字
  • $1: 第一个参数
  • $2: 第2个参数
  • $3: 第三个参数

应用:执行脚本的时候, 可以给脚本传递参数, 在脚本内部接收这些参数, 需要使用位置变量

# 建立脚本test.sh
#!/bin/bash
echo "hello , world, $0"
echo "第一个参数: $1"
echo "第2参数: $2"
echo "第3个参数: $3"
echo "第4个参数: $4"
echo "第5个参数: $5"
echo "第6个参数: $6"

# 执行test.sh
$ ./test.sh 11 22 3 4 5 6 aa bb
hello , world, ./test.sh
第一个参数: 11
第2参数: 22
第3个参数: 3
第4个参数: 4
第5个参数: 5
第6个参数: 6

特殊变量

$$: 脚本进程执行之后对应进程的ID
$#: 获取传递的参数的个数
$@: 给脚本传递的所有的参数
$?: 脚本执行完成之后的状态, 失败>0 or 成功=0

举例:

# test.sh
#!/bin/bash
echo "hello , world, $0"
echo "第一个参数: $1"
echo "第2参数: $2"
echo "第3个参数: $3"
echo "第4个参数: $4"
echo "第5个参数: $5"
echo "第6个参数: $6"
echo "传递的参数个数: $#"
echo "传递的所有的参数: $@"
echo "当前脚本的进程ID: $$" 

$ ./test.sh aa bb cc dd ee ff 8 9 0 
hello , world, ./test.sh
第一个参数: aa
第2参数: bb
第3个参数: cc
第4个参数: dd
第5个参数: ee
第6个参数: ff
传递的参数个数: 9
传递的所有的参数: aa bb cc dd ee ff 8 9 0
当前脚本的进程ID: 47946

# 脚本执行状态查看
$ echo $?
0 -> 成功
非0 -> 失败

数组

数组定义

array_name=(value1 value2 ... valuen)

# 举例:
array=(A B "C" D)

元素使用

${array_name[index]}

# 举例
echo "第一个元素为: ${array[0]}"

在这里插入图片描述

注意:观察上面四条echo语句

  • 第二个打印语句没有使用花括号,shell命令解析器就没有解析成数组的第0个元素
  • 而是把数组的第一个元素和[0]都打印了出来

获取所有元素

# 使用 * h和 @ 符号
echo "所有元素为: ${array[*]}"
echo "所有元素为: ${array[@]}"

在这里插入图片描述

其他

取命令执行之后的结果值

# 取值的两种方式:
var=$(shell命令)
var=`shell命令`   #反单引号(esc同一个)

在这里插入图片描述

引号的使用(单引号,双引号)

# 双引号
echo "当前文件: $var" # 打印的时候会将var中的值取出并输出
# 单引号
echo '当前文件: $var' # 将字符串原样输出

$*与$@区别

#作用:都是引用所有参数。
#不同点:例如在脚本运行时写了三个参数 1、2、3,,则 “ * “ 等价于 “1 2 3”(传递了1个参数),而 “@” 等价于 “1” “2” “3”(传递了3个参数)。

三、基本运算

Shell支持的运算符:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

数值运算

在bash中,变量的默认类型是字符串类型,而字符串类型是不能进行数值运算的,所以shell提供了很多方式来实现数值运算。

expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

# 例如,两个数相加(注意使用的是反引号 ` 而不是单引号 ‘):

#!/bin/bash
val=`expr 2 + 2`
echo "2+2=:$val"

注意:

  1. 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2。。
  2. 完整的表达式要被“反单引号” ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。

数值关系运算

a=10
b=20
if [ $a -eq $b ]
then
  echo "$a -eq $b : a 等于 b"
else
  echo "$a -ne $b : a 不等于 b"
fi

这里用到了 -eq,判断两个数值是否相等

常见数值关系测试运算符

nt1 -eq int2如果int1 等于int2,则返回真
int1 -ne int2如果int1 不等于int2,则返回真
int1 -lt int2如果int1 小于int2,则返回真
int1 -le int2如果int1 小于等于int2,则返回真
int1 -gt int2如果int1 大于int2,则返回真
int1 -ge int2如果int1 大于等于int2,则返回真

布尔运算

a=10
b=20
if [ $a != $b ]
then 
  echo "$a != $b : a 不等于 b"
else
  echo "$a == $b : a 等于 b"
fi

测试时使用的逻辑操作符

-a逻辑与,操作符两边均为真,结果为真,否则为假。&&
-o逻辑或,操作符两边一边为真,结果为真,否则为假。||
!逻辑否,条件为假,结果为真。

比较 -a 与 &&, -o 与 ||, ! test 与 test !

  • -a-o 作为测试命令的参数用在测试命令的内部,
  • &&|| 则用来运算测试的返回值,
  • ! 为两者通用。

字符串运算

a="abc"
b="efg"
if [ $a = $b ] # 判断两个字符串是否相等
then
  echo "$a = $b : a 等于 b"
else
  echo "$a = $b : a 不等于 b"
fi

常见字符串测试

-z string字符串string 为空串(长度为0)时返回真
-n string字符串string 为非空串时返回真
str1 = str2字符串str1 和字符串str2 相等时返回真
str1 == str2同 =
str1 != str2字符串str1 和字符串str2 不相等时返回真
str1 < str2按字典顺序排序,字符串str1 在字符串str2 之前
str1 > str2按字典顺序排序,字符串str1 在字符串str2 之后

文件测试运算

file="C:/helloworld.sh"
if [ -r $file ]  # 测试问价是否可读
then 
  echo "文件可读"
else
  echo "文件不可读"
fi

文件状态测试

-b filename当filename 存在并且是块文件时返回真(返回0)
-cfilename当filename 存在并且是字符文件时返回真
-d ​pathname当pathname 存在并且是一个目录时返回真
-e ​pathname当由pathname 指定的文件或目录存在时返回真
-f ​filename当filename 存在并且是正规(普通)文件时返回真
-gpathname当由pathname 指定的文件或目录存在并且设置了SGID 位时返回真
-h/-Lfilename当filename 存在并且是符号链接文件时返回真 (或 filename)
-kpathname当由pathname 指定的文件或目录存在并且设置了"粘滞"位时返回真
-pfilename当filename 存在并且是命名管道时返回真
-rpathname当由pathname 指定的文件或目录存在并且可读时返回真
-sfilename当filename 存在并且文件大小大于0 时返回真
-S ​filename当filename 存在并且是socket 时返回真
-tfd当fd 是与终端设备相关联的文件描述符时返回真
-upathname当由pathname 指定的文件或目录存在并且设置了SUID 位时返回真
-w ​pathname当由pathname 指定的文件或目录存在并且可写时返回真
-x ​pathname当由pathname 指定的文件或目录存在并且可执行时返回真
-O ​pathname当由pathname 存在并且被当前进程的有效用户id 的用户拥有时返回真(字母O 大写)
-G ​pathname当由pathname 存在并且属于当前进程的有效用户id 的用户的用户组时返回真
file1-ntfile2file1 比file2 新时返回真
file1-ot ​file2file1 比file2 旧时返回真
f1-eff2files f1 and f2 are hard links to the same file

条件测试

test

test <测试 表达式>
# test命令和 < 测试表达式 >之间至少有一个空格  

[]

 [ < 测试表 达式> ]
# 该方法和 test 命令的用法一样, [] 的边界和内容之间至少有一个空格

[[]]

 [[ < 测试 表达式> ]]
# 比 test 和 [] 更新的语法格式。 [[]] 的边界和内容之间至少有一个空格。 [[]] 中可以使用通配符等进行模式匹配

四、一些命令

echo命令

# 用法
echo string

# 显示字符串,双引号可以省略,默认就是字符串格式
echo "hello world"
echo hello world

# 显示双引号
echo "\"hello world\""
echo \"hello world\"

# 显示换行,转义字符
# -e 开启转义
echo -e "OK! \n"   
echo It is a test

#显示变量的值
name=xiaoming
echo "$name is my name"

#显示结果定向至文件
echo It is a test > myfile

#原样输出字符串,不进行转义或取变量(用单引号)
echo '$name\"'

# 显示执行结果
echo `date`


显示变量的值:

在这里插入图片描述

printf命令

# 用法
printf  format-string  [arguments...]
	# format-string:为格式控制字符串
	# arguments:为参数列表。

# 例子:
printf "%-10s %-8s %-4s\n" Name Sex Weight-kg
printf "%-10s %-8s %-4.2f\n" GuoJing male 66.1234
printf "%-10s %-8s %-4.2f\n" YangGuo male 48.6543
printf "%-10s %-8s %-4.2f\n" GuoFu female 47.9876
# 输出:(通过格式控制,输出非常整齐)
Name       Sex      Weight-kg
GuoJing    male     66.12
YangGuo    male     48.65
GuoFu      female   47.99

printf的转义序列

序列说明
\a警告字符,通常为ASCII的BEL字符
\b后退
\c抑制(不显示)输出结果中任何结尾的换行字符(只在%b格式指示符控制下的参数字符串中有效),而且,任何留在参数里的字符、任何接下来的参数以及任何留在格式字符串中的字符,都被忽略
\f换页(formfeed)
\n换行
\r回车(Carriage return)
\t水平制表符
\v垂直制表符
两个反斜杠一个字面上的反斜杠字符
\ddd表示1到3位数八进制值的字符。仅在格式字符串中有效
\0ddd表示1到3位的八进制值字符

输入,输出重定向

通常linux系统命令的输入和输出都是终端(标准输入,输出),有时候我们需要重新定向到其他地方。

命令说明
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)。

输出重定向

# 命令执行command1然后将输出的内容存入file1
# 注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,使用>>追加操作符。
command1 > file1

输入重定向

# 从文件获取输入
command1 < file1

输入输出同时重定向

# 执行command1,从文件infile读取内容,然后将输出写入到outfile中
command1 < infile > outfile

重定向深入了解

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

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。 默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。
# stderr 重定向到 file
command 2 > file  # 将错误信息保存到文件

# 将 stdout 和 stderr 合并后重定向到 file
command > file 2>&1

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。

# 将两个 delimiter 之间的内容(document) 作为输入传递给 command。
command << delimiter
    document
delimiter

/dev/null 文件

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

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

# 将command的执行输出丢弃
command > /dev/null 2>&1

五、程序控制语句

if条件判断

# if语句
# 注意事项:
	# if 和 []直接有一个空格
	# [ 条件 ] : 条件的前后都有空格
	# else if => elif

if [ 条件判断 ];then  #命令写到同一行需要加分号
	逻辑处理 -> shell命令
	xxx
	xxxx
	xxxx
fi                      # 结束

# 另一种写法
if [ 条件判断 ]
then
	逻辑处理 -> shell命令
	xxx
	xxx
fi

# if ... elif .. fi
if [ 条件判断 ];then
	逻辑处理 -> shell命令
	xxx
	xxxx
	xxxx
elif [ 条件判断 ];then
	shell命令
elif [ 条件判断 ];then
	shell命令
elif [ 条件判断 ];then
	shell命令
else
	shell命令
fi

#!/bin/bash
# 需要对传递到脚本内部的文件名做判断
if [ -d $1 ];then
    echo "$1 是一个目录!"                                      
elif [ -s $1 ];then
    echo "$1 是一个文件, 并文件不为空"
else
    echo "$1 不是目录, 有可能不存在, 或文件大小为0"
fi

for和while循环

# shell中的循环 for/ while
# 语法: for 变量 in 集合; do;done
for var in 集合;do
	shell命令
done
=================
while 测试条件
do
    shell命令
done
#!/bin/bash
# 对当前目录下的文件进行遍历
list=`ls`  #反单引号
for var in $list;do
    echo "当前文件: $var"
    echo '当前文件: $var'   # 单引号,原样输出                        
done
# 运行脚本
$ ./for.sh   
当前文件: a
当前文件: $var
当前文件: abc
当前文件: $var
当前文件: for.sh
当前文件: $var
当前文件: if.sh
当前文件: $var
当前文件: test.sh
当前文件: $var

六、shell函数

# 注意:没有函数修饰, 没有参数列表
# 格式
funcName(){
	# 得到第一个参数
	arg1=$1
	# 得到第2个参数
	arg2=$2
	函数体 = shell命令 + 逻辑循环和判断
}

# 没有参数列表, 但是可以传参
# 函数调用
funcName aa bb cc dd #调用没有括号

# 函数调用之后的状态: 
0 -> 调用成功
非0 -> 失败
#!/bin/bash
# 判断传递进行来的文件名是不是目录, 如果不是, 创建...
# 定义函数
is_directory()
{
    # 得到文件名, 通过参数得到文件名
    name=$1
    if [ -d $name ];then
        echo "$name 是一个目录!"
    else
        # 创建目录
        mkdir $name
        if [ 0 -ne $? ];then
            echo "目录创建失败..."
            exit
        fi  
        echo "目录创建成功!!!"                                                                               
    fi  
}
# 函数调用
is_directory $1


# 有返回值函数
#!/bin/bash
funWithReturn(){
    echo "Two nums add each other..."
    echo "Input the first num1:"
    read num1
    echo "Input the second num2:"
    read num2
    echo "Two nums are $num1 and $num2"
    return $(($num1+$num2))
}
# 函数调用
funWithReturn 
# 使用参数
echo "num1 + num2 = $?"

七、文件包含

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

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

参考学习资料

https://www.bookstack.cn/read/ShellBasicProgramming/README.md

https://blog.csdn.net/qq_59323864/article/details/126549723

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值