入门与规范
shell脚本编写规范
- 脚本文件后缀名:本质上就是一个文本文件,建议保存为.sh
- 首行格式规范:
#! /bin/bash 含义:声明shell解析器
注释格式
# 单行注释
:<<!
多行注释
!
脚本文件的执行方式
- 解析器执行方式
#相对路径,bash也一样
sh helloworld.sh
#全路径
sh /root/helloworld.sh
- 仅路劲执行方式
# 注意:这种方式脚本文件需要有执行权限
./helloworld.sh
变量
环境变量
linux系统加载Shell的配置文件中定义的变量共享给所有的Shell程序
环境变量所在的配置文件
-
全局配置文件(系统级环境变量)
-
/etc/profile
-
/etc/profile.d/*.sh
-
/etc/bashrc
-
-
个人配置文件(用户及环境变量)
- 当前用户/.basg_profile
- 当前用户/.bashrc
环境变量相关指令
-
查看当前Shell 环境变量:env
-
查看所有变量(系统环境变量+自定义变量+函数):set
自定义系统环境变量
- 编辑/etc/profile全局配置文件
- 添加环境变量:
export var1=var
- 重载配置文件:
source /ect/profile
环境变量加载流程原理
Shell工作环境
- 交互式与非交互式
- 交互式:需要用户输入
- 非交互式:不需要参与
- 登录与非登录
- 登录:正常用户需要登录才能使用linux系统
- 非登录:一些特殊的用户,不需要登录就可以进入linux系统的Shell环境
- 识别登录与非登录环境:$0
- -bash Shell登录环境
- bash Shell非登录环境
- 工作环境切换
- 用户切换时
- 登录:
su -l root
- 非登录:
su root
- 登录:
- 登录->非登录:
bash
- 以工作化环境执行脚本:
sh -l / bash -l
- 用户切换时
加载的流程
用户登录后,开始加载以下流程
自定义变量
自定义局部变量
-
定义:定义在一个脚本文件的变量
-
定义语法:
var_name=value
-
定义规则:
- 等号两侧不能有空格
- 变量的默认类型是字符串,无法直接进行数值运算
- 变量的值如果有空格,必须用双引号括起来
自定义常量:realonly
- 定义:
realonly var_name
自定义全局变量:export
- 定于语法:
export var_name=value
- 父子Shell环境:在A.sh中执行B.sh,则A.sh为父Shell环境,即调用者为父
- 全局变量的定义:在父环境中定义,在子环境中也可以使用
变量增删改查
- 查:
$var_name
${var_name}
- 改:
var_name=newValue
- 删:
unset var_name
字符串变量
3种格式及其区别
- 单引号:无法解析字符串中的变量
- 双引号:最稳定,可以解析变量,可以转义,可以包含空格
- 无引号:不能包含空格
字符串操作
- 获取长度:
${#var}
- 拼接:
"${var1}${var2}"
- 截取:点击查看
特殊符号变量
-
$n:接收脚本文件入参
-
$1-$9,代表获取第一到第九的参数
-
第10个参数以上:
${数字}
-
$0 用于获取脚本名称
-
参数传入语法:
sh helloworld.sh param1 param2
-
-
$#:获取输入参数的个数
-
∗ / */ ∗/@:都是获取所有输入参数并当成一个字符串
- 不使用双引号,功能是一样的
- 使用双引号
- $* 输出的是一个整体
- $@输出“$1”,"$2","$3"
- 在循环时体现区别,$@可以
for var in $@
,$* 不能
-
$?:获取上一个Shell或者函数的返回值
- 每个Shell都有一个返回值,用以说明时候执行成功
- 一般来说,0表示成功,非0表示失败
-
$:获取当前Shell系统的进程ID号
变量数组
注意:Bash Shell 只支持一维数组
数组的定义
()表示数组,空格来分隔
array_name=(item1 item2 item3) #方式1
array_name=(item1[3] item2[2] item3[1]) #方式2,个人认为有个一个废物语法,[3]表示下标
#注意=两侧,不能有空格
数组的获取
-
通过下标获取
${arr[1]}
-
使用@或*获取所有元素
${arr[@]} ${arr[*]}
-
获取数组的个数
${#arr[@]} ${#arr[@]}
-
获取指定元素的长度
${#arr[1]}
数组拼接与删除
数组拼接
arr1=(${arr2[@]} ${arr3[@]})
arr1=(${arr2[*]} ${arr3[*]})
数组删除
unset arr[1] #删除元素
unset arr #删除整个数组
常用内置命令
含义
- 是Shell内部的命令,可以直接使用,与之对应的是外部脚本文件
- 两者(内置命令与外部脚本文件)的区别
- 内置命令:Shell进程的一部分(指令在内存),在进程内部执行
- 外部脚本文件:存储在磁盘上,运行需要fork新的进程运行
- 使用type命令可以判断是内部还是外部
设置别名:alias
alias ls="ls -l" #设置别名,最常见的应用就是 ll
unalias ll #删除别名
输出字符串:echo
echo -n "输出内容" #输出不换行的字符串
echo -e "hello\nworld" #-e 执行转义字符:\n:换行 \c:清除换行
读取控制台输入:read
简介:用于从标准输入中读取数据并给变量赋值,若标准输入重定向,这可以从文件中读取数据
read [-options] [var1 var2 ....] #基础表达式
options:
意味着Shell获取命令行数据时,可以实现以下功能:
- 读取数据
- 指定结束字符串
- 是否转义
- 读取指个数的字符 :
read -n 1 var
- 设置提示信息 :
read -p "请输入地址:" addr
- 拒绝转义
- 输入不重现 :
read -p "请输入密码" pwd -s
- 设置输出超时时间,配合
#?
使用 :read -t 10 var #10内完成输入,否则失败
- 设文件为输入源
结束当前Shell环境进程:exit
exit 可以返回一个状态码,使用
$?
可以获取状态码
exit #返回0,一般任务命令执行成功
exit 1 #数字的范围建议0-255
设置变量属性:declare
#设置变量的属性
#a:索引数组,A:关联数组(map),
#r:只读,x:设置为环境变量,
#i:整型变量,f:函数
declare [+/-][aArxif][变量名称=初始值]
#查看全部变量与函数
declare
declare -f #所有函数定义
declare -F #所有函数名称列表
#定义关联数组(map),关联数组只能用declare
declare -A aMap=([key]=value [key1]=value2 ...)
${aMap[key]} #获取值
运算符
总结:数值的计算(()),比较判断用[[]],复杂数学计算用bc
算术运算符
expr命令:求值表达式
result=`expr 1+2` #这里使用的是反引号``,且只能进行整数运算
(())命令
((a=b+1))
a=$((b+1))
((a=35+2,b=1+5)) #多个表达式用,隔开
#(())中可以忽视空格。((a=1+6))和((a = 1+6))是等价的
let命令
#let 只能用于赋值
let a=b+1
let a=b+1 b=c+1 #多个用空格隔开
$[]命令
#$[]表达式内部不用对变量赋值
b=$[a+1]
比较运输符
整数比较
(($a<$b)) #a小于b,成立返回0,不成立1
字符串比较
#以下方法可以比较字符串,整数,小数,成立返回0,不成立1
[[$a==$b]] #比较中==与=同价
[$a \< $b]
[[$a < $b]] #[]。遇到<、>是需要转义,[[]]不需要,且[]字符串不能有空格
[[$a>$b && $a==$b]] #字符串比较不支持,>=、<=,只能用这种方式表达
[-z $a] #字符串是否为0
[-n $a] #字符串是否不为0
[$a] #字符串是否不为空
布尔与逻辑运算符
#布尔
[!$a \< $b]
[$a>$b -o $a==$b]
[$a>$b -a $a==$b]
#逻辑
[[!$a \< $b]]
[[$a>$b && $a==$b]]
[[$a>$b && $a==$b]]
##总结
# 布尔运行在[]中
# 逻辑运行在[[]]或者(())中。其中!只能运行在[[]]中
文件测试运算符
[[-d file]]#是否是目录
[[-f file]] #是否是普通文件
[[-r file]] #是否可读
[[-w file]] #是否可写
[[-x file]] #是否可执行
[[-s file]] #是否为空
[[-e file]] #是否存在
[[file1 -nt file2]] #file1是否比file2新
[[file1 -ot file2]] #file1是否比file2旧
bc命令:linux的内置计算器
-
语法:
bc [options] [参数]
- 使用内置函数:bc -l
- 显示告警信息:bc -w
- 不显示欢迎信息:bc -q
- 退出:quit
-
内置变量
- scala:结果精度
- ibase:输入的进制
- obase:输出的进制
- last或者.:获取最近打印的结果
-
内置函数
- s(x):计算正弦值,x为数值,即Π=360°
- c(x):计算余弦值
- a(x):计算正反切
- l(x):计算x的自然对数
- e(x):计算e的x次方
- j(n,x):计算n到x的阶数
-
互动式的数学运行
- 标准计算器的使用:即输入表达式,回车输出结果
- 也可以直接读取整个文件:
bc file
,一次性把表达式全输入,结果全输出
-
非互动式的管道运算
echo "e(2)" | bc #以管道的方式把计算公式传给bc,bc计算后返回结果 echo "obase=2;7" | bc #多表达式同行,用;隔开 var_name=`echo "e(2)" | bc` #使用反引号给变量赋值 var_name=$(echo "e(2)" | bc) #使用$()给变量赋值,但不是所有linux系统都支持
-
非互动式输入重定向bc运算
使用bc,以流的方式,进行多行运算,估计八辈子都用用不到
流程控制语句
if else 语句
## 注意点:shell中成功为0,失败为1
## test的功能[]的效果一致
#if语句
if [[$a > $b]]
then
ehco "a>b"
fi
if [[$a > $b]] ;then ;fi #一行时,用;隔开,多命令同行都是用;隔开,下同
#if else语句
if [[$a > $b]]
then
echo "ture"
else
echo "false"
fi
#if elif else语句
if [[$a > $b]]
then
ehco "a>b"
elif [[$a == $b]]
then
ehco "a=b"
else
ehco "a<b"
fi
case 语句
# case的匹配模式支持,数字,字符串,部分正则表达式:
# *:类似default
# [abc]:满足abc中任意一个即可
# [1-5]:数值范围
# |:多条件
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
while 与 until 语句
#until与while相反,false时执行
while 条件
do
command1
command2
...
commandN
continue;
break;
done
# 无线循环
while true
while :
for 语句
#枚举遍历
for i in 1 2 3;do ; done
#范围遍历
for i in {1..100};do ;done
#类C遍历
for((i=1;i<100;i++));do ;done
select 语句
#用于交互式的菜单选择,没有结束条件,只能使用break跳出
#会输出菜单项在控制台上供选择
#经常配合case使用
select var in itme1 itme2 itme3
do
break;
done
函数
系统函数
basename
:获取文件名dirname
:获取文件所在目录
普通函数语法
shell函数与shell程序的区别:外部脚本文件在新进程中运行,函数在原进程运行
#函数定义
[ function ] fun()
{
[return 返回值] #返回值的范围在[0-255];无返回值,返回最后一条命令的结果,
}
#函数调用
fun 参数1 参数2 参数3 ...
a=$? #获取返回值
#与shell程序一样 使用$1 $2 $3 $*等获取参数
默认输入输出
文件名 | 类型 | 文件描述符 |
---|---|---|
stdin | 标准输入 | 0 |
stdout | 标准输出 | 1 |
stderr | 标准错误 | 2 |
重定向语法
命令 | 作用 |
---|---|
> file ; < file | 覆盖方式重定向 |
>> file | 追加方式重定向 |
< file1 >file2 | 从file1读取,结果输出到file2 |
fd> file ; fd >>file | 把fd的数据重定向到文件中 |
> file fd1>&fd2 | 两个fd都输出到fd中 |
Shell 工具
- cut工具:按列分割,并提取 err: Template render error: (unknown path)
- sed工具:字段增删改查
- awk工具:按表格处理数据
- sort工具:排序