什么是shell脚本
现在常用的shell是升级版的,全称是bash shell
shell计算机语言是将用户输入指令通过bash解释器翻译给linux系统
写一个.sh脚本时开头要写#! /bin/bash指定bash解释器
shell变量
变量规则和作用域
shell语言是弱类型语言,声明变量时不需要定义变量类型
变量是临时存储空间,当关机,退出文件该变量就不存在了
变量与值之间不能写空格。
name=“hellokitty”
echo $name #或者echo $ n a m e {{name}} name
变量名规则 只能包含数字、字母、下划线,但不能以数字开头,不能用标点符号
变量名严格区分大小写
父shell是bash
输入pstree命令可以查看层级关系,输入的命令是在哪个bash里
本地变量举例
var1=''我是父层级“
输入bash,进入子层级,echo var1是空值因为var1是父层级作用域变量
exit当前bash
再输入echo var1得出我是父层级
像$$PATH就是全局变量在哪一级shell都能输出
pstree是查看进程树
每次调用bash/sh解释器执行脚本,都会开启一个shell,因此不保留当前变量,通过pstree命令查看进程树
不执行子shell 调用source 或者点 .命令,在当前shell环境加载脚本,因此保留变量
source make_vars.sh
echo name
面试题
cat test.sh
user1=hellokityy
sh test.sh
echo $user1
上面答案是空 因为sh命令是开启一个shell,输出是子shell里的变量,子shell没有对这个变量赋值
cat test.sh
user1=malloty
source test.sh
echo $user1
上题的答案是malloty
环境变量又称全局变量
cat查看文件
echo $PATH 查看路径
which 查看命令的路径
su [选项][用户名] 切换用户身份的命令
vim文件名,不管文件存不存在都进入输入模式
每个用户都有自己的环境变量配置文件 ~/.bash_profile ~/.bashrc,且以个人配置文件优先加载变量、读取变量
=当你需要给所有用户使用某个变量时,写入全局配置文件/etc/profile
set命令是找到当前shell环境下的所有变量,包括全局变量。set lwc -l 这个命令行是统计变量个数
检查系统环境变量的命令
set lgrep ^[变量名] #输出该变量的值
env只显示全局变量 env lwc -l 统计全局变量的个数
declare 输出所有变量 和set功能相似
export只显示和设置环境变量的值
怎么找出linux系统所有的变量?用set或者declare命令
readonly设置变量为只读 只有shell结束,只读变量失效
怎么输出所有环境变量的值??
首先export所有环境变量, 然后用export lawk -F '[ :=]' 'print $3' #显示的环境变量是固定格式,那么以:=间隔前后字符串,输出第三个,就是环境变量的值
bash支持多命令行:多个命令之间用分号隔开
bash启动后各配置文件的加载顺序
是系统全局变量文件/etc/profile → 然后是/etc/profile.d目录下的系统脚本和登录时需要加载的自定义脚本便于登录后立即运行 →运行$Home/.bashrc→等等→运行/ect/bashrc
特殊变量
特殊的参数变量
$* 和 $@ 不加双引号时都输出bash命令里的所有参数。
加双引号后"$*“将bash命令里的参数合成一整个字符串输出。”$@"将bash命令里的参数分别单独作为字符串输出,有几个参数输出几个字符串
$#获取shell脚本后面参数个数的总数。
$n 获取shell脚本后面第几个参数,n在[1,9]则直接使用$1,$3,$9;如果大于9,则使用${10},参数空格隔开
$0 获取shell脚本文件名 文件路径
#!/bin/bash
echo "print each param from \"\$*\""
for var in "$*"
do
echo "$var"
done
echo "print each param from \"\$@\""
for var in "$@"
do
echo "$var"
done
特殊状态变量
$? 判断上一次执行命令返回状态,0正确,非0失败。
$$ 取得当前shell脚本进程ID号
$!取得上一次进程的PID
$_ 取得上一次执行命令的最后一个参数
man bash 可以搜索man手册 --->Special Parameters 搜索bash的特殊变量
linux命令ls 查看文件清单,显示指定目录下的文件及文件夹清单
#!/bin/bash
#获取参数个数,与2比较,如果个数不同则返回119
[ $# -ne 2 ] && {
echo "must be 2 args"
exit 119
}
echo "there are 2 args"
怎么让程序后台执行
# 让程序在后台执行,并且重定向结果输出到黑洞文件中
nohup xxx & 1> /dev/null
#举例百度:让其后台执行,查找该进程
nohup ping baidu.com & 1> /dev/null
ps -eflgrep ping
$!取得上一次进程的PID
echo $!
21973
$$ 取得当前shell脚本进程ID号
#!/bin/bash
#获取参数个数,与2比较,如果个数不同则返回119
[ $# -ne 2 ] && {
echo "must be 2 args"
exit 119
}
echo "there are 2 args"
echo "当前脚本Id:$$"
shell子串
bash基础的内置命令
echo 显示
# echo命令用分号间隔可以输出两条语句;默认语句后加换行符
echo 你真聪明;echo 你真可爱
你真聪明
你真可爱
# echo -n 命令使输出不换行
echo -n 你真聪明;echo 你真可爱
你真聪明你真可爱
echo -n 你真聪明;echo -n 你真可爱
你真聪明你真可爱[root@httlinux shell_program]#
# echo -e 识别字符串中的特殊字符
echo "我是\n凯蒂猫"
我是\n凯蒂猫
echo -e "我是\n凯蒂猫"
我是
凯蒂猫
printf打印
printf “你好\t我是\t小明”
你好 我是 小明[root@httlinux shell_program]#
printf “你好\t我是\t小明\n”
你好 我是 小明
eval 执行多条命令
eval ls;cd /tmp
exec 不创建进程,执行后续程序,并且执行完毕后自动exit
exec date #显示时间后退出当前会话
shell字符串的花式用法
基础语法
${变量} 返回变量值
${#变量} 返回变量的长度
name="htt"
${#name}
3
${变量:start} 返回变量第start索引开始的字符
name="hantt" #字符串的索引是从0开始
echo ${#name:4} #返回字符包含索引4的字符
tt
${变量:start:length} #提取索引start后的length长度的字符
name="hantt"
echo ${#name:4:1} #返回字符索引4开始的1个字符
t
${变量#匹配项} #从变量头开始删除变量中与匹配项相同的最短字符串
echo ${name#tt}
han
${变量##匹配项} #从变量头开始删除变量中与匹配项相同的最长字符串
${变量%匹配项} #从变量结尾开始删除变量中与匹配项相同的最短字符串
${变量%%匹配项} #从变量结尾开始删除变量中与匹配项相同的最长字符串
${变量/替换变量中的哪个子串pattern/替换结果string} #用string代替第一个匹配的pattern
${变量//替换变量中的哪个子串pattern/替换结果string} #用string代替所有匹配的pattern
echo $name | wc -l 统计行数
echo $name | wc -L 输出最长那一行的字符个数
vim test1.txt
12345
123456
12345678
cat test1.txt | wc -l
3
cat test1.txt | wc -L
8
expr --help #显示expr命令的帮助文档
expr length "${变量}" #统计变量长度
awk ^C #awk搭配length函数
name="hantt"
echo "${name}" | awk '{print length($0)}'#统计变量长度
5
字符串统计长度命令这么多,哪一个命令最快?
time命令,统计命令执行时长
for语法
#for写成一行的语法
for num in {1..5};do echo $num; done
1
2
3
4
5
#for写成多行的语法
for num in {1..5}
do
echo $num
done
seq自动生成序列的方法
seq 3
1
2
3
seq -s ":" 3
1:2:3
shell测试
#读取命令read -t 5时间限制,5s内输入;-p屏幕输出内容,定义两个参数接收
read - t 5 -p "what's your name,how old are you" name age
what's your name,how old are youhantt 30 #两参数间加空格,否则按一个接收age为空
echo $name $age
hantt 30
test
test -e test.txt #测试文件是否存在,存在则返回0,不存在返回非0
echo $? #$?接收返回值
0