shell教程

Published: · LastMod: April 07, 2024 · 1815 words

shell笔记 🔗

  • 单引号变量,不识别特殊语法
  • 双引号变量,可以识别特殊语法
  1. 每次调用bash/sh解释器执行脚本,都会开启一个子shell,因此不会保留当前的shell变量
  2. 通过source命令或者./方式执行脚本,会在当前shell环境加载脚本,因此会保留变量
1
name=`ls`  // 反引号会保留当前命令执行的结果

环境变量可以在命令行中临时创建,但是用户退出shell终端,变量即将丢失,要永久生效,就必须修改环境变量配置文件

先执行.bash_profile, 再执行.bashrc

  • set命令,可以查找所有的变量
  • env命令,可以查找全局变量
  • declare, 输出所有的变量
  • export 显示和设置环境变量

unset 删除环境变量赋值

1
2
3
4
5
$0   获取脚本文件名,以及脚本的文件路径
$n   传给脚本的参数位置,表示
$#   获取参数的总个数
$*   获取所有参数
$@   获取所有参数

$*$@的区别

不加双引号时,大家输出时一样的

加上双引号后

  • “$*” : 会将所有参数从整体上看做一份数据,而不是把每个参数都看做一份数据
  • “$@”: 将每个参数看做一个独立的数据
1
2
3
4
$?  上一次命令执行状态返回值, 0是执行成功, 非0就是执行失败
$$  当前shell脚本的进程号
$!  上一次后台进程的PID
$_  取上一次执行脚本的最后一个参数

image-20220712211005313

echo 🔗

1
2
-e 解析字符串中的特殊字符
-n 不换行输出

eval 🔗

1
同时执行多个命令

exec 🔗

1
不创建子进程,执行后续命令,且执行完毕后,自动exit

shell子串 🔗

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash

name="hello world"

echo ${name}
echo ${#name}
echo ${name:3}   # 裁剪下标3之后的所有字符
echo ${name:3:4} # 提取3之后4个字符
echo ${name#wor} # 从前向后删除最短匹配字符串
echo ${name##rld}# 从前向后删除最长匹配字符串
echo ${name%ell} # 从后向前删除最短匹配字符串
echo ${name%%rld}# 从后向前删除最长匹配字符串
# 替换 1个斜杠只替换1个,2个斜杠替换所有的
echo ${name/world/jack}
echo ${name//o/e}


#hello world
#11
#lo world
#lo w
#ld
#hello world
#hello world
#hello wo
#hello jack
#helle werld
1
2
3
4
5
6
7
wc -l  # 统计字符长度
wc -L  # 找到文件中最长的一行,并且输出这一行的字符数量

expr length "${name}" # 统计变量字符长度

# 利用awk统计长度
echo "${name}" | awk '{printf length($0)}'
1
2
3
4
5
➜  ~ time for n in {1..10000}; do char=`seq -s ":" 100`; echo ${char}&>/dev/null;done

real 0m12s # 实际执行时间
user       # 用户态执行时间
sys 			 # 内核执行时间
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# 如果parameter为空,返回word字符串,赋值给result变量
result=${parameter:-word}

# 如果parameter为空,word赋值给parameter,并且赋值给result变量
result=${parameter:=word}

# 如果parameter为空,word当作stderr输出,否则输出变量值
${parameter:?word}

# 如果parameter为空,什么都不做,否则返回word
${parameter:+word}
1
2
3
1. source和点执行脚本在当前shell环境执行生效
2. bash sh解释器执行脚本开启subshell开启子shell运行脚本
3. ./script 都会指定shebang,通过解释器运行开启子shell运行脚本

检测是否在子shell环境中 🔗

1
2
# 如果是0,则是在当前shell环境中执行的,否则就是开辟子shell执行的
BASH_SUBSHELL

子shell嵌套运行 🔗

一个括号()开启一个子shell

1
(pwd;(pwd;(echo $BASH_SUBSHELL)))

内置命令、外置命令 🔗

  • 内置命令:系统启动时加载入内存,常驻内存,执行效率更高,占用资源
  • 外置命令:用户需要从硬盘中读取程序,加载到内存中

read接收命令行参数 🔗

1
read -t 15 -p "名字,年龄:"

条件测试 🔗

  • test 测试表达式
  • [测试表达式]
  • [[测试表达式]]
  • ((测试表达式))

test 🔗

1
test -e test.sh # 判断文件是否存在, 存在就是真,否则为假, 使用$?输出值

在条件测试中使用变量必须使用双引号

1
[ -f "${filename}" ] && echo yes || echo no
在[]和test中在[[]]和(())中说明
-a&&and和
-o||or或
!!not非

正则表达式 🔗

1
2
3
4
5
6
7
8
read -p "请输入字符" var1

[[ ! "$var1" =~ [1-3] ]] && {
	echo "你输入的字符必须是1,2,3"
	exit 1
}

echo "你输入的字符是${var1}"

if…then 🔗

1
2
3
4
5
6
7
8
9
if <条件表达式>
then
	....
elif <条件表达式>
then
	....
else
	....
fi

内存 🔗

1
free -m  # 查看系统内存

函数 🔗

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 1. 
function funcName() {
	# ....
	return returnValue
}

# 2. 
function funcName{
  # ....
	return returnValue
}

# 3. 
funcName() {
  # ....
	return returnValue
}

函数执行概念 🔗

  • 执行shell函数,直接写函数名字即可
  • 函数必须先定义,再执行,自上而下加载
  • 函数体内定义的变量,为局部变量
  • 函数体内添加return语句,作用是退出函数,且赋予返回值给调用该函数的程序
  • return和exit
    • return上结束函数的执行
    • exit是结束shell环境
  • 函数如果写在一个单独的文件内,需要用source读取
  • 函数内使用local关键字,定义局部变量