helloworld入门
使用编辑器vim
创建并添加语句
vim helloworld.sh
#! /bin/bash
echo 'helloworld'
#! /bin/bash
是指此脚本使用/bin/bash来解释执行。
echo
输出语句
chmod ug+x helloworld.sh # 修改文件执行权限
./helloworld.sh # 执行脚本
chmod命令
u
表示user 文件或目录的所有者
g
表示group 与文件属主有相同组ID的所有用户
o
表示others
a
表示所有用户,a为系统默认值
w
写的权限
x
执行权限
r
读权限
数字设定法
计算方法:r=4,w=2,x=1
- 7 = 4+2+1=读+写+执行
- 5 = 4+1=读+执行
- 1 = 执行
等同于:
chmod u=rwx,g=rx,o=x helloworld.sh
编写规范与建议
1.脚本存放目录需要统一
2.shell脚本的结尾以 .sh
3.脚本开头要有解释器如#!/bin/bash 或者#!/usr/bin/env bash
4.脚本开头注意加时间、作者、联系邮箱、脚本作用等信息
# huhao egon 2022-11-06 version 1 des: xx
5.关键代码应该用#号加上注释
6.成对的符号尽量一次性写出来,防止遗漏
- 例如大括号
{}
,中括号[ ]
,小括号()
,单引号''
,双引号""
,反引号``等
7.括号的保留空格习惯
- 中括号
[ ]
两端需要留有空格,不然会报错。书写时即可留出空格然后书写内容。 - 如果不知道大括号
{ }
,中括号[ ]
,小括号( )
,到底哪种括号需要两端留空格,可以在书写这些括号的时候两端都保留空格来进行书写,这样可以有效避免因空格导致的各种错误。
8.流程控制语句一次性书写完再添加内容
#if语句格式一次书写完成
if 条件内容
then
条件成立后执行的代码
fi
变量
1.定义
变量名=变量值
2.变量定义规则
区分大小写,一般大写
不能有特殊符号
变量值有空格要用单双引号
变量名字不可以用数字开头
等号两边不能有任何空格,如 A = 3 错的
3.变量的使用
基本方式
A=1546
echo $A
输出:
1546
4.删除变量
删除变量unset age
变量值的来源
1.直接赋值
#! /bin/bash
ip="10.10.10.10"
age=18
now_date1=`date "+%F"`
now_date2=$(date "+%F")
2.从脚本的参数获取,即从命令获取
- $0 是本身
- $1 是第一个参数
- $2 是第二个参数
- …
- ${10} 10以上就要用{}括起来
创建.sh脚本 test.sh
#! /bin/bash
if [ $1 = "start" ];then
echo "starting"
elif [ $1 = "stop" ];then
echo "stopping"
elif [ $1 = "restart" ];then
echo "restartting"
else
echo "Usage: ./test.sh start:stop:restart"
fi
运行
chmod +x test.sh # 设置权限
./test.sh stop # stop 是传入的变量
3.与用户交互来获取变量值
read -p "请输入您的账号:" name
#! /bin/bash
db_name="huhao"
db_pwd="123456"
read -p "请输入您的账号:" name
read -p "请输入您的密码:" pwd
if [ $name = $db_name ] && [ $pwd = $db_pwd ]:then
echo "登录成功"
else
echo "登录失败"
fi
运行
chmod +x test.sh
./test.sh
请输入您的账号:huhao
请输入您的密码:123456
登录成功
4.命令结果赋值给变量
``(反撇号)或$()
A=`hostname`
echo $A
输出:
huhaodeMacBook-Pro.local
交互式定义变量
read [选项] 变量名
选项 | 功能 |
---|---|
-p | 定义提示用户的信息 |
-n | 定义字符数(限制输入长度) |
-s | 不显示(用户输入的内容) |
-t | 定义超时时间 |
#! /bin/bash
read -p "请输入你的名字:" name
echo $name
read -s -p "请输入密码:" pwd
echo $pwd
定义有类型的变量
declare [选项] 变量名=变量值
选项 | 功能 |
---|---|
-i | 将变量看成整数 |
-r | 定义只读变量 |
-a | 定义普通数组,查看普通数组 |
-A | 定义关联数组;查看关联数组 |
-x | 将变量通过环境导出 |
普通数组
#! /bin/bash
# 直接赋值
arr1=("抽烟" "酒" "烫头")
echo ${arr1[0]} # 结果:抽烟
echo ${arr1[1]} # 结果:酒
echo ${arr1[2]} # 结果:烫头
# 先创建后赋值
declare -a arr2
arr2[0]=12
arr2[1]=34
arr2[2]=56
echo ${arr2[0]} # 结果:12
echo ${arr2[1]} # 结果:34
echo ${arr2[2]} # 结果:56
# 指定下标对应为什么值
arr3=([2]=3.3 [1]=1.1 [3]=4.4)
echo ${arr3[3]} # 结果:4.4
echo ${arr3[2]} # 结果:3.3
echo ${arr3[1]} # 结果:1.1
echo ${array2[0]} # 结果: ,因为没有定义
关联数组
#! /bin/bash
declare -A info=(["name"]="huhao" ["age"]=28 ["sex"]="male")
echo ${info["name"]} # 结果:huhao
echo ${info["age"]} # 结果:28
echo ${info["sex"]} # 结果:male
系统变量
内置变量 | 含义 |
---|---|
$? | 上一条命令执行后返回的状态;状态值为0表示执行正常,非0表示执行异常或错误 |
$0 | 当前执行的程序或脚本名 |
$# | 脚本后面接的参数的个数 |
$* | 脚本后面所有参数,参数当成一个整体输出,每一个变量参数之间以空格隔开 |
$@ | 脚本后面所有参数,参数是独立的,也是全部输出 |
$1-$9 | 脚本后面的位置参数,$1表示第1个位置参数,依次类推 |
${10}-${n} | 扩展位置参数,第10个位置变量必须用{}大括号括起来(2位数字以上扩起来) |
$$ | 当前所在进程的进程号,如echo $$ |
$! | 后台运行的最后一个进程号(当前终端) |
!$ | 调用最后一条命令历史中的参数 |
判断文件类型
判断参数 | 含义 |
---|---|
-e | 判断文件是否存在(任何类型文件) |
-f | 判断文件是否存在并是一个普通文件 |
-d | 判断文件是否存在并且是一个目录 |
-L | 判断文件是否存在并且是一个软连接文件 |
-b | 判断文件是否存在并且是一个块设备文件 |
-S | 判断文件是否存在并且是一个套接字文件 |
-c | 判断文件是否存在并且是一个字符设备文件 |
-p | 判断文件是否存在并且是一个命名管道软件 |
-s | 判断文件是否存在并且是一个非空文件(有内容) |
#! /bin/bash
while true
do
read -p "输入文件名称或者目录(输入break退出循环):" filename;
if [ $filename = "break" ]
then
echo "已退出循环";
break;
fi
if [ -e $filename ]
then
echo "经检测,输入的文件或者目录存在...";
else
echo "经检测,输入的文件或者目录不存在,请重新输入"
fi
if [ -f $filename ]
then
echo "进一步检测到,输入的是一个文件且为一个普通文件"
#判断该文件是否为空
if [ -s $filename ]
then
echo "该文件非空"
else
echo "该文件为空"
fi
#判读文件是否是软链接
if [ -L $filename ]
then
echo "该文件是一个软链接";
fi
# 判读文件是否可读
if [ -r $filename ]
then
echo "该文件可读";
else
echo "该文件不可读";
fi
#判断文件是否可写
if [ -w $filename ]
then
echo "该文件可写入";
else
echo "该文件不可写入";
fi
#该文件是否可执行
if [ -x $filename ]
then
echo "该文件可执行";
else
echo "该文件不可执行";
fi
else
if [ -c $filename ]
then
echo "该文件为字符设备文件";
fi
if [ -b $filename ]
then
echo "该文件为块设备文件"
fi
if [ -p $filename ]
then
echo "该文件为管道文件";
fi
fi
if [ -d $filename ]
then
echo "进一步检查到,输入的是一个目录";
fi
done
判断整数 常用
参数 | 含义 |
---|---|
-eq | 相等 |
-ne | 不等 |
-gt | 大于 |
-lt | 小于 |
-ge | 大于等于 |
-le | 小于等于 |
算数运算符
符号 | 中文词义 |
---|---|
+ | 加 |
- | 减 |
* | 乘 |
/ | 除 |
% | 取余 |
# 浮点运算
bc #bc计算器
# 整数运算
expr
$(())
$[]
let
#! /bin/bash
x=1
y=2
expr $x+$y # 结果:3
expr $x \* $y # 结果:2,乘法需要加 \ ,因为 * 有特殊意义
echo $((1+2)) # 结果:3
echo $(( $x + $y )) # 结果:3
echo $[ $x + $y ] # 结果:3
let z=x+y
echo $z # 结果:3
echo "5.6*3.2+6.7^2"|bc #62.7
判断字符串 常用
判断参数 | 含义 |
---|---|
-z | 判断是否为空字符串,字符串长度为0成立 |
-n | 判断是否为非空字符串,字符串长度不为0成立 |
string1 = string2 | 判断字符串是否相等 |
string1 != string2 | 判断字符串是否不相等 |
#!/bin/bash
x1=""
y2="123abc"
[ -n "$x1" ]
echo $? # 1,x的长度为0
[ -n "$y1" ]
echo $? # 0,y的长度不为0
x2=""
y2="123abc"
[ -z "$x2" ]
echo $? # 0,x的长度为0
[ -z "$y2" ]
echo $? # 1,y的长度不为0
x3=""
y3="123abc"
[ "$x3" = "$y3" ]
echo $? # 1,x不等于y
x4=""
y4="123abc"
[ "$x4" != "$y4" ]
echo $? # 0,x不等于y
补充[[ ]]
[[ ]]
和 [ ]
基本一样,不同的是[[ ]]
支持正则表达式
#!/bin/bash
[ $# -ne 1 ] && echo "只能传入一个参数" && exit
# 只能是数字
[[ ! $1 =~ ^[0-9]+$ ]] && echo "只能传入数字" && exit
echo "ko ----> $1"
常量
常量:不变的量
readonly m=111 # 使用常量关键字
AGE=18 # 或者使用大写变量名来提示自己这是常量
获取变量值的长度
#! /bin/bash
x="hello"
y=123456
z=3.12
echo ${#x} # 结果:5
echo ${#y} # 结果:6
echo ${#z} # 结果:4
切片
#! /bin/bash
msg="hello123"
echo ${msg:1} # 结果:ello123 ,从第一个开始切
echo ${msg:1:3} # 结果:ell ,从第一个开始切,切三个
截断
#! /bin/bash
url="www.huhaowb.com"
# 从左开始截断
echo ${url#www.} # 结果:huhaowb.com
echo ${url#*.} # 结果:huhaowb.com ,截断到第一个点
echo ${url##*.} # com ,截断到最后第一个点
# 从右开始截断
echo ${url%.com} # 结果:www.huhaowb
echo ${url%.*} # 结果:www.huhaowb ,从最后截断第一个点
echo ${url%%.*} # 结果:www ,从最后截断到最后一个点
替换
#! /bin/bash
url="www.huhaowb.com"
echo ${url/huhaowb/baidu} # 结果:www.baidu.com
echo ${url/c/C} # 结果:www.huhaowb.Com
# 替换所有
echo ${url//h/H} # 结果:www.HuHaowb.com
if语句
# 单分支
if [ 条件1 ];then
代码1
代码2
...
fi
# 双分支
if [ 条件1 ];then
代码1
代码2
...
else
代码1
代码2
...
fi
# 多分支
if [ 条件1 ];then
代码1
代码2
...
elif [ 条件2 ];then
代码1
代码2
...
elif [ 条件3 ];then
代码1
代码2
...
else
代码1
代码2
...
fi
case语句
case $x in
1)
代码1
代码2
代码3
;;
2)
代码1
代码2
代码3
;;
3|4|5) # 变量为3、4、5都可以进入这个代码块
代码1
代码2
代码3
;;
...
*)
代码1
代码2
代码3
esac
案例:输入名字,输出系统权限身份
#!/bin/bash
read -p "please input your name: " name
if [ -z "$name" ];then
echo "必须输入用户名"
fi
case $name in
"root")
echo "管理员"
;;
"huhao")
echo "普通用户"
;;
*)
echo "访客"
esac
while循环
条件为真则运行循环体代码,直到条件变为假则结束循环
while 条件
do
代码1
代码1
代码1
done
案例:打印0~7
#! /bin/bash
count=0
while [ $count -le 7 ] #小于等于7
do
echo $count
let count++
done
until循环
条件为假则运行循环体代码,直到条件变为真则结束循环
until 条件
do
代码1
代码1
代码1
done
案例:打印0~7
#! /bin/bash
count=0
until [ $count -gt 7 ] #大于7
do
echo $count
let count++
done
break终止本层循环
#! /bin/bash
count=0
while :
do
if [ $count -le 7 ];then
break
fi
echo $count
let count++
done
continue终止本次循环
#! /bin/bash
count=0
while [ $count -le 7 ]
do
if [ $count -eq 4 ];then
continue
fi
echo $count
let count++
done
for循环
for x in 参数值1 参数值2 参数值3
do
代码1
代码1
代码1
done
案例:遍历桌面文件
#! /bin/bash
for x in `ls Desktop`
do
echo "hello $x"
done
select选择循环
#! /bin/bash
select choice in {"退出","取款","转账","查询余额"}
do
echo "选项是:$choice"
case $choice in
"退出")
break
;;
"取款")
echo "正在取款"
;;
"转账")
echo "正在转账"
;;
"查询余额")
echo "正在查询余额"
;;
*)
echo "其他功能还没有开发"
esac
done
函数
function f1(){
echo "第一种方式"
}
function f2{
echo "第二种方式"
}
f1(){
echo "第三种方式"
}
函数参数
function f1(){
echo "$1"
echo "$2"
echo "$3"
echo "$4"
echo "$5"
}
f1 111 222 333 444 555
函数返回值
1.使用return返回值
使用return返回值,只能返回1-255的整数
函数使用return返回值,通常只是用来供其他地方调用获取状态,因此通常仅返回0或1;0表示成功,1表示失败
2.使用echo返回值
使用echo可以返回任何字符串结果
通常用于返回数据,比如一个字符串值或者列表值
获取return返回值
使用$?接收上一程序的返回值状态,也就是return的值
#! /bin/bash
getResult(){
if [ -d "Desktop" ];then
return 1
else
return 0
fi
}
main(){
getResult
res=$?
echo ${res}
if [[ $res -eq 1 ]]; then
echo 1
else
echo 0
fi
}
main
通过echo返回一个任意值
在函数最后使用echo打印一个值,在调用该函数的地方,可以通过$(function_name)把结果传给一个新的变量,也就获取了函数的处理结果
#! /bin/bash
function foo(){
echo $1;
}
result=$(foo 33)
echo result is ${result}