szy@szy:~$ cat /etc/shells
# /etc/shells: valid login shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
szy@szy:~$ echo $SHELL
/bin/bash
szy@szy:~$ mkdir scripts
szy@szy:~$ cd scripts/
szy@szy:~/scripts$ vim hello.sh
#!/bin/bash
echo "hello,world"
szy@szy:~/scripts$ bash hello.sh
hello,world
szy@szy:~/scripts$ sh hello.sh
hello,world
szy@szy:~/scripts$ ll
总用量 12
drwxrwxr-x 2 szy szy 4096 12月 2 08:26 ./
drwxr-xr-x 23 szy szy 4096 12月 2 08:26 ../
-rw-rw-r-- 1 szy szy 31 12月 2 08:26 hello.sh
szy@szy:~/scripts$ chmod +x hello.sh
szy@szy:~/scripts$ ll
总用量 12
drwxrwxr-x 2 szy szy 4096 12月 2 08:26 ./
drwxr-xr-x 23 szy szy 4096 12月 2 08:26 ../
-rwxrwxr-x 1 szy szy 31 12月 2 08:26 hello.sh*
# xxx.sh文件添加可执行权限
chmod +x xxx.sh
# xxx.sh文件当前用户添加可执行权限
chmod a+x xxx.sh
# 最高权限
chmod 777 xxx.sh
szy@szy:~/scripts$ ./hello.sh
hello,world
szy@szy:~$ scripts/hello.sh
hello,world
szy@szy:~/scripts$ source hello.sh
hello,world
szy@szy:~$ source scripts/hello.sh
hello,world
szy@szy:~$ type source
source 是 shell 内建
szy@szy:~/scripts$ . hello.sh
hello,world
szy@szy:~$ mkdir she
szy@szy:~$ cd she/
szy@szy:~/she$ vim test.sh
szy@szy:~/she$ ll
总用量 12
drwxrwxr-x 2 szy szy 4096 12月 2 18:00 ./
drwxr-xr-x 24 szy szy 4096 12月 2 18:00 ../
-rw-rw-r-- 1 szy szy 33 12月 2 18:00 test.sh
szy@szy:~/she$ chmod a+x test.sh
szy@szy:~/she$ ll
总用量 12
drwxrwxr-x 2 szy szy 4096 12月 2 18:00 ./
drwxr-xr-x 24 szy szy 4096 12月 2 18:00 ../
-rwxrwxr-x 1 szy szy 33 12月 2 18:00 test.sh*
szy@szy:~/she$ ./test.sh
hello, world
#!/bin/bash
echo "hello, world"
常用系统变量
$ HOME、$ PWD、$ SHELL、$ USER等
环境变量
export:查看环境变量
echo $PATH:输出环境变量的值
help echo:查看echo命令的帮助信息
szy@szy:~/scripts$ echo $HOME
/home/szy
szy@szy:~/scripts$ env
szy@szy:~/scripts$ set
基本语法
定义变量(变量赋值):变量名=变量值,注意,=前后不能有空格
销毁变量:unset 变量
声明静态变量:readonly 变量,注意:不能销毁unset
变量定义规则
变量名称可以由字母、数字和下划线组成,但是不能以数字开头,环境变量名建议大写。
等号两侧不能有空格。
在bash中,变量默认类型都是字符串类型,无法直接进行数值运算。
局部变量变成全局变量使用export
子shell更改不会影响父shell
typeset和declare两个内部命令定义变量
变量的值如果有空格,需要使用双引号或单引号括起来:
echo “hello ${x}”:双引号可以正常输出变量值
echo ‘hello ${x}’:单引号输出字符串
变量的四种引用方式
$变量名
${变量名}
“$变量名”
“${变量名}”
测试
szy@szy:~/scripts$ a=2
szy@szy:~/scripts$ echo $a
2
szy@szy:~/scripts$ echo $my_var
szy@szy:~/scripts$ my_var=hello
szy@szy:~/scripts$ echo $my_var
hello
szy@szy:~/scripts$ my_var=Hello
szy@szy:~/scripts$ echo $my_var
Hello
szy@szy:~/scripts$ my_var="hello, world"
szy@szy:~/scripts$ echo $my_var
hello, world
szy@szy:~/scripts$ my_var='hello, world'
szy@szy:~/scripts$ echo $my_var
hello, world
szy@szy:~/scripts$ echo $a
2
szy@szy:~/scripts$ a=1+5
szy@szy:~/scripts$ echo $a
1+5
szy@szy:~/scripts$ a=$((1+5))
szy@szy:~/scripts$ echo $a
6
szy@szy:~/scripts$ a=$[8+5]
szy@szy:~/scripts$ echo $a
13
szy@szy:~/scripts$ readonly b=5
szy@szy:~/scripts$ b=10
-bash: b: 只读变量
szy@szy:~/scripts$ echo $b
5
szy@szy:~/scripts$ unset a
szy@szy:~/scripts$ unset b
-bash: unset: b: 无法取消设定: 只读 variable
szy@szy:~/scripts$ declare a
szy@szy:~/scripts$ declare -i b
read (选项) 变量名
选项:
-p:指定读取值时的提示符
-t:指定读取值时等待时间(秒)如果-t不加表示一直等待,时间到则退出
-n:读取n个字符之后返回,而不是等到读取换行符
szy@szy:~/she$ read -n 3
323
szy@szy:~/she$
# 读取到o结束
szy@szy:~/scripts$ read -d o x
dewewoszy
# 读取到c结束,多个字符时只看第一个
@szy:~/scripts$ read -d cde x
dsdc
szy@szy:~/scripts$
szy@szy:~/scripts$ vim read_test.sh
szy@szy:~/scripts$ chmod +x read_test.sh
szy@szy:~/scripts$ ./read_test.sh
请输入您的姓名:sgz
你好 sgz
szy@szy:~/scripts$ ./read_test.sh
请输入您的姓名:你好
szy@szy:~/scripts$
read_test.sh文件内容
#!/bin/bash
read -t 10 -p "请输入您的姓名:" name
echo "你好 $name"
n为数字,$0代表该脚本名称,$1-$9代表第一个到第九个参数,十以上的参数需要用大括号包含,如 ${10}
#!/bin/bash
echo "hello, world"
# $1,输入一个参数
echo "hello, $1"
szy@szy:~/scripts$ ./hello.sh 你好
hello, world
hello, 你好
#!/bin/bash
# 双引号会认为值变量
#echo "=======$n======"
# 单引号会原样输出
echo '=======$n======'
echo script name: $0
echo 1st paramter: $1
echo 2nd parameter: $2
szy@szy:~/scripts$ ./parameter.sh abc def
=======$n======
script name: ./parameter.sh
1st paramter: abc
2nd parameter: def
获取所有输入参数个数,常用于循环,判断参数的个数是否正确以及加强脚本的健壮性。
#!/bin/bash
echo '=======$n======'
echo script name: $0
echo 1st paramter: $1
echo 2nd parameter: $2
echo parmamter number: $#
szy@szy:~/scripts$ ./parameter.sh
=======$n======
script name: ./parameter.sh
1st paramter:
2nd parameter:
parmamter number: 0
szy@szy:~/scripts$ ./parameter.sh dbd ccc 333
=======$n======
script name: ./parameter.sh
1st paramter: dbd
2nd parameter: ccc
parmamter number: 3
$* :这个变量代表命令行中所有的参数, 把所有的参数看成一个整体
$@:这个变量也代表命令行所有的参数,不过 $@ 把每个参数区分对待,类似一个数组,可以使用for循环遍历里面的参数
#!/bin/bash
echo '=======$n======'
echo script name: $0
echo 1st paramter: $1
echo 2nd parameter: $2
echo '=======$#======'
echo paramter number: $#
echo '=======$*======'
echo $*
echo '=======$@======'
echo $@
szy@szy:~/scripts$ ./parameter.sh dbd ccc 222
=======$n======
script name: ./parameter.sh
1st paramter: dbd
2nd parameter: ccc
=======$#======
paramter number: 3
=======$*======
dbd ccc 222
=======$@======
dbd ccc 222
最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行:如果这个变量的值为非0(具体是哪个数,由命令自己来决定),则证明上一个命令执行不正确了。
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ parmeter.sh
parmeter.sh:未找到命令
szy@szy:~/scripts$ echo $?
127
运算符可以加空格也可以不加空格
szy@szy:~/scripts$ a=1+2
szy@szy:~/scripts$ echo $a
1+2
szy@szy:~/scripts$ expr 1+2
1+2
szy@szy:~/scripts$ expr 1 + 2
3
szy@szy:~/scripts$ expr 5 - 2
3
szy@szy:~/scripts$ expr 5 * 2
expr: 语法错误
szy@szy:~/scripts$ expr 5 \* 2
10
szy@szy:~/scripts$ echo $[5*2]
10
szy@szy:~/scripts$ echo $((5*2))
10
szy@szy:~/scripts$ a=$[6+8]
szy@szy:~/scripts$ echo $a
14
szy@szy:~/scripts$ s=$[(2+3)*4]
szy@szy:~/scripts$ echo $s
20
#!/bin/bash
# 可以加空格也可以不加空格
sum=$[$1+$2]
# sum=$[$1 + $2]
echo sum=$sum
szy@szy:~/scripts$ ./add.sh 25 89
sum=114
1真,0假;1真执行2值;1假执行3值
注意:三目运算符与条件测试的真假相反
表达式1?表达式2:表达式3
szy@szy:~/scripts$ aa=0
szy@szy:~/scripts$ bb=1
szy@szy:~/scripts$ cc=2
szy@szy:~/scripts$ dd=3
# aa为假
szy@szy:~/scripts$ echo $((aa?cc:dd))
3
# bb为真
szy@szy:~/scripts$ echo $((bb?cc:dd))
2
szy@szy:~/scripts$ aa=10
szy@szy:~/scripts$ bb=20
szy@szy:~/scripts$ let xx=$aa+$bb
szy@szy:~/scripts$ echo $xx
30
szy@szy:~/scripts$ xx=$(($aa+$bb))
szy@szy:~/scripts$ echo $xx
30
szy@szy:~/scripts$ xx=$[$aa+$bb]
szy@szy:~/scripts$ echo $xx
30
注意:
1.条件非空即为true,[ aaa ]返回true,[ ]返回false。
2. 0真,1假。
3. 判断时需要空格
szy@szy:~/scripts$ a=hello
szy@szy:~/scripts$ echo $a
hello
szy@szy:~/scripts$ test $a = hello
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ test $a = Hello
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ a=Hello
szy@szy:~/scripts$ test $a = Hello
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ $a = Hello ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ $a = hello ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/she$ a=hello
szy@szy:~/she$ [[ $a = Hello ]]
szy@szy:~/she$ echo $?
1
szy@szy:~/she$ [[ $a = hello ]]
szy@szy:~/she$ echo $?
0
szy@szy:~/scripts$ [ sfsfaf ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ $a != Hello ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ $a != hello ]
szy@szy:~/scripts$ echo $?
0
注意:如果字符串之间的比较,用等号 “=” 判断相等;用“!=”判断不等,如下。
szy@szy:~/scripts$ [ 2 = 8 ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ 2 = 2 ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ 2 -lt 8 ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ 2 -gt 8 ]
szy@szy:~/scripts$ echo $?
1
-r 有读的权限
-w 有写的权限
-x 有执行的权限
-b 当前文件存在,其为块文件时测试为真
-d 当前路径存在,且为目录时测试为真
-e 文件存在
-f 文件存在并且是一个常规的文件
szy@szy:~/scripts$ touch test
szy@szy:~/scripts$ [ -r hello.sh ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -w hello.sh ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -x hello.sh ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -r test ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -w test ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -x test ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ -e /home/szy/info ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ -e /home/szy/sum.sh ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -f add.sh ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ [ -d add.sh ]
szy@szy:~/scripts$ echo $?
1
szy@szy:~/scripts$ [ -d /home/szy/ ]
szy@szy:~/scripts$ echo $?
0
szy@szy:~/scripts$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 12月 2 08:14 /dev/sda
szy@szy:~/scripts$ [ -b /dev/sda ];echo $?
0
字符串对比:
注意:
使用符号时两侧必须有空格
[[ ]] 括号左右必须有空格
这点与赋值时不同,赋值时两侧不能有空格
szy@szy:~/scripts$ [[ "abc" == "abd" ]];echo $?
1
szy@szy:~/scripts$ [[ "abc" == "abc" ]];echo $?
0
szy@szy:~/scripts$ [[ "abc" == "abd" ]];echo $?
1
szy@szy:~/scripts$ [[ "abc" > "aaa" ]];echo $?
0
szy@szy:~/scripts$ [[ "abc" > "abc" ]];echo $?
1
szy@szy:~/scripts$ [[ "abc" != "abc" ]];echo $?
1
szy@szy:~/scripts$ [[ "abc" != "abd" ]];echo $?
0
szy@szy:~/scripts$ s1=abc
szy@szy:~/scripts$ s2=bcd
szy@szy:~/scripts$ [[ $s1 == $s2 ]];echo $?
1
szy@szy:~/scripts$ [[ $s1 > $s2 ]];echo $?
1
szy@szy:~/scripts$ [[ $s1 < $s2 ]];echo $?
0
注意:
[ 条件判断式 ],中括号和条件判断式之间必须有空
if 后要有空格
if [ 条件判断式 ];then
程序
fi
或者
if [ 条件判断式 ]
then
程序
fi
if [ 条件判断式 ]
then
程序
elif [ 条件判断式 ]
then
程序
else
程序
fi
#!/bin/bash
if [ "$1"x = "sgz"x ]
then
echo "hello, sgz"
fi
szy@szy:~/scripts$ ./if.sh
szy@szy:~/scripts$ ./if.sh 小米
szy@szy:~/scripts$ ./if.sh sgz
hello, sgz
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
...省略其它分支...
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
注意:
(1)case行尾必须为单词 “in”,每一个模式匹配必须以右括号“)”结束。
(2)双分号“;;”表示命令序列结束,相当于java中的break。
(3)最后的"*)"表示默认模式,相当于java中的default。
#!/bin/bash
case $1 in
1)
echo "one"
;;
2)
echo "two"
;;
3)
echo "three"
;;
*)
echo "number else"
;;
esac
szy@szy:~/scripts$ ./case.sh 1
one
szy@szy:~/scripts$ ./case.sh 6
number else
for (( 初始值;循环控制条件;变量变化 ))
do
程序
done
# list元素集合,通常是数组变量,循环时将list中相应位置的元素赋给变量,通过变量输出
for 变量 in list
do
程序
done
#!/bin/bash
sum=0
for ((i=1;i<=$1;i++))
do
sum=$[$sum+$i]
done
echo $sum
#!/bin/bash
array=(1 2 3 4 5)
for num in ${array[@]} #获取数组索引0-4
do
echo $num
done
szy@szy:~/scripts$ for os in linux windows macos; do echo $os;done
linux
windows
macos
szy@szy:~/scripts$ for i in {1..100}; do sum=$[$sum+$i]; done; echo $sum
5050
比较 $* 和 $@ 区别
$ * :整体
$@:独立
可以通过加引号区分
不加引号:正常输出
加引号:逐个输出 $@
不加引号:正常输出
#!/bin/bash
echo '=========$*=========='
for para in $*
do
echo $para
done
echo '=========$@=========='
for para in $@
do
echo $para
done
szy@szy:~/scripts$ ./paramter_for.sh a b c d e
=========$*==========
a
b
c
d
e
=========$@==========
a
b
c
d
e
#!/bin/bash
echo '=========$*=========='
for para in "$*"
do
echo $para
done
echo '=========$@=========='
for para in "$@"
do
echo $para
done
szy@szy:~/scripts$ ./paramter_for.sh a b c d e
=========$*==========
a b c d e
=========$@==========
a
b
c
d
e
while [ 条件判断式 ]
do
程序
done
#!/bin/bash
# for实现
sum=0
for ((i=1;i<=$1;i++))
do
sum=$[$sum+$i]
done
echo $sum
# while实现
a=1
while [ $a -le $1 ]
do
# 老写法
# sum2=$[ $sum2 + $a ]
# a=$[$a + 1]
# 新写法
let sum2+=a
let a++
done
echo $sum2
szy@szy:~/scripts$ ./for.sh 100
5050
5050
#!/bin/bash
array=(1 2 3 4 5)
length=${#array[@]} # 获取数组长度
i=0
while(($i<$length))
do
echo ${array[i]} # 输出索引i对应的值
let "i++"
done
until:条件测试为假时执行循环语句
select:和用户进行交互,它是死循环,必须使用break,exit或Ctrl+C退出脚本。
continue:终止本次循环
break:终止循环
szy@szy:~/scripts$ a1=(1 2 3 4 5)
szy@szy:~/scripts$ echo ${a1[0]}
1
szy@szy:~/scripts$ declare -a a2
szy@szy:~/scripts$ a2=("a" "b" "c" "d" "e")
szy@szy:~/scripts$ echo ${a2[1]}
b
szy@szy:~/scripts$ a3=(1
> 2
> 3
> 4
> 5
> )
szy@szy:~/scripts$ echo ${a3[2]}
3
szy@szy:~/scripts$ date="t e d u"
szy@szy:~/scripts$ a4=($date)
szy@szy:~/scripts$ echo ${a4[3]}
u
szy@szy:~/scripts$ a5[0]=1
szy@szy:~/scripts$ a5[1]=2
szy@szy:~/scripts$ a5[2]=3
szy@szy:~/scripts$ a5[3]=4
szy@szy:~/scripts$ a5[4]=5
szy@szy:~/scripts$ echo ${a5[4]}
5
szy@szy:~/scripts$ a6=([0]=1 [1]=2 [2]=3 [3]=4 [4]=5)
szy@szy:~/scripts$ echo ${a6[1]}
2
# 销毁数组中某个索引元素
unset 数组名[索引]
# 销毁整个数组
unset 数组名
szy@szy:~/scripts$ unset a6[2]
szy@szy:~/scripts$ echo ${a6[2]}
szy@szy:~/scripts$ echo ${a6[1]}
2
szy@szy:~/scripts$ unset a6
szy@szy:~/scripts$ echo ${a6[1]}
function funname()
{
函数体
}
funname()
{
函数体
}
function funname()
{
函数体
return n
}
funname()
{
函数体
return n
}
注意:
1、必须在调用函数地方之前,先声明函数,shell脚本是逐行运行。不会像其它语言一样先编译。
2、函数返回值,只能通过$?系统变量获得,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。return后跟数值n(0-255)。
#!/bin/bash
# 声明函数
function add()
{
s=$[$1 + $2]
echo "和:"$s
}
read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b
# 调用函数
add $a $b
szy@szy:~/scripts$ ./fun_test.sh
请输入第一个整数:35
请输入第二个整数:67
和:102
#!/bin/bash
function add()
{
s=$[$1 + $2]
return $s
}
read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b
add $a $b
# $? 与 return 结果代码,0-255,当我们计算超出该范围会错误
echo "和:" $?
#!/bin/bash
function add()
{
s=$[$1 + $2]
echo $s
}
read -p "请输入第一个整数:" a
read -p "请输入第二个整数:" b
sum=$(add $a $b)
echo "和:" $sum
#!/bin/bash
function add()
{
echo first function
}
add2()
{
echo second function
}
add
add2
#!/bin/bash
function add()
{
echo first function
return 3
}
add
echo 值为:$?
$变量、${变量名}、“$变量名”、“${变量名}”:取值,输出获取变量的值,使用变量值时使用
$0:获取脚本文件名
$1-$9:代表获取第一个到第九个参数,十以上用大括号包含,如:${10}
$#:获取所有输入参数个数,常用于循环
$*:这个变量代表命令行中所有的参数,整体
$@:这个变量也代表命令行所有的参数,依次遍历参数,独立;不加引号正常输出;
加引号逐个输出
$?:最后一次执行的命令的返回状态,0真,非0假
${数组名[索引]}:来获取该索引下标对应的元素
${数组名[@]}:获取数组索引下标
${#数组名[@]}:获取数组长度
双引号和单引号可以输出字符串中的空格,双引号变量值,单引号输出字符串