What is Shell?
Shell是一个命令行解释器,它接收应用程序/用户命令,然后调用系统操作内核。
Shell还是一个功能相当强大的编程语言,易编写、易调试、灵活性强。
cat /etc/shells
echo $SHELL
脚本一**#!/bin/bash**开头(指定解析器)
# 1. touch hello.sh
# 2.vim hello.sh
# 3.输入下面内容
#!/bin/bash
echo "Hello World!"
#4.执行hello.sh
sh hello.sh
#或 bash hello.sh
#或使用绝对路径:
# sh /home/myShell/hello.sh
# bash /home/myShell/hello.sh
# 5.打印结果
Hello World!
#6.使用./hello.sh 执行时提示权限不够
[root@MiWiFi-R4CM-srv myShell]# ./hello.sh
-bash: ./hello.sh: 权限不够
# 6.1 授权
chmod 777 hello.sh
# 6.2 再使用 ./ 执行hello.sh
./hello.sh
#或使用绝对路径,如下:
/home/myShell/hello.sh
为什么使用 sh 或bash执行shell脚本时不需要执行权限,而使用**./**执行shell脚本时需要执行权限呢?
- 使用sh或bash时,本质时bash解析器帮你执行脚本,所以脚本本身不需要执行权限;
- 使用./执行shell时,本质是脚本需要自己执行,所有需要执行权限
需求:创建一个shell脚本,本脚本可以在 /home/myShell/目录下建立test.txt文件,并向test.txt文件中增加“I love shell”;
#!/bin/bash
cd /home/myShell/
touch test.txt
echo "I love shell" >> test.txt
$HOME $PWD $ SHELL $USER等
echo $HOME
echo $PWD
echo $SHELL
echo $USER
# 定义一个变量A,赋值为A
A=1
# 取变量的值
echo $A
unset A
readonly B=2
变量名可以由字母、数字和下划线组成,但不能以数字开头,环境变量名建议大写;
赋值符号(=)两边不能有空格;
在bash,中变量默认类型都是字符串类型,无法直接进行数字运算;
变量的值如果有空格,需要使用双引号或单引号括起来,如下
D="I love shell" 或 D='I love shell'
export 变量名
$n: n为数字,$0代表该脚本名称,$1- 9 代表第一个至第九个参数,十以上的参数需要用大括号括起来,如 9代表第一个至第九个参数,十以上的参数需要用大括号括起来,如 9代表第一个至第九个参数,十以上的参数需要用大括号括起来,如{10}
实操案例
输出该及爱哦本文件名称,输入参数1和输入参数2的值
新建文件名为 paramaters.sh 的shell,内容如下
#!/bin/bash
echo "$0 $1 $2"
执行paramaters.sh
[root@MiWiFi-R4CM-srv myShell]# sh inputoutput.sh a b
inputoutput.sh a b
$#功能描述:获取所有输入参数的个数;如果定义了参数但为输入,则为0;常用与循环
以paramaters.sh为例
#!/bin/bash
echo "$0 $1 $2"
echo $#
# 不输入参数的情况
[root@MiWiFi-R4CM-srv myShell]# sh paramaters.sh
inputoutput.sh
0
# 输入参数的情况
[root@MiWiFi-R4CM-srv myShell]# sh paramaters.sh hello "this is shell"
inputoutput.sh hello this is shell
2
[root@MiWiFi-R4CM-srv myShell]# sh paramaters.sh hello "this is shell" world
inputoutput.sh hello this is shell
3
KaTeX parse error: Undefined control sequence: \* at position 1: \̲*̲:这个变量代表命令行中所有的参…*是把所有的参数看成一个整体;
@ : 这个变量也代表命令行中所有的参数,但 @:这个变量也代表命令行中所有的参数,但 @:这个变量也代表命令行中所有的参数,但@把每个参数区分对待
# paramaters.sh 内容如下
#!/bin/bashi-R4CM-srv myShell]#
echo "$0 $1 $2"
echo $#
echo $*
echo $@
# 执行
[root@MiWiFi-R4CM-srv myShell]# bash paramaters.sh p1 p2 p3
paramaters.sh p1 p2
3
p1 p2 p3 # $* 输出所有参数
p1 p2 p3 # $@ 输出所有参数
$?: 最后一次执行的命令的返回状态。如果这个变量的值为0,证明上一个命令正确执行;如果这个变量的值为非0(具体是哪个参数,由命令自己来决定),则证明上一个命令执行不正确
[root@MiWiFi-R4CM-srv myShell]# sss
-bash: sss: 未找到命令
[root@MiWiFi-R4CM-srv myShell]# echo $?
127 #未正确执行
[root@MiWiFi-R4CM-srv myShell]# ./hello.sh
Hello World!
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 # 正确执行
# 加法
[root@MiWiFi-R4CM-srv myShell]# ADD=$((2+3))
[root@MiWiFi-R4CM-srv myShell]# echo $ADD
5
# 加、除、减
[root@MiWiFi-R4CM-srv myShell]# SUB=$[(3+5)/2-2]
[root@MiWiFi-R4CM-srv myShell]# echo $SUB
2
# 混合运算
[root@MiWiFi-R4CM-srv myShell]# MULT=$[(5+5)-4*3/2%5]
[root@MiWiFi-R4CM-srv myShell]# echo $MULT
9
[root@MiWiFi-R4CM-srv myShell]# expr 4+3
4+3
# +
[root@MiWiFi-R4CM-srv myShell]# expr 4 + 3
7
# -
[root@MiWiFi-R4CM-srv myShell]# expr 6 - 3
3
# *
[root@MiWiFi-R4CM-srv myShell]# expr 5 \* 3
15
# /
[root@MiWiFi-R4CM-srv myShell]# expr 6 / 3
2
[root@MiWiFi-R4CM-srv myShell]# expr 6 % 5
1
# 计算 (2 + 4) * 5 的值
# 先使用``包住括号内的运算,然后在*5,如下:
[root@MiWiFi-R4CM-srv myShell]# expr `expr 2 + 4` \* 5
30
[root@MiWiFi-R4CM-srv myShell]#
[condition] (注意condition前后要有空格)
注意:条件非空即为true,[yuan]返回true,[]返回false
比较符 | 说明 |
---|---|
= | 字符串比较 |
-lt | 小于(less than) |
-le | 小于等于(less equal) |
-eq | 等于(equal) |
-gt | 大于(greater than) |
-ge | 大于等于(greater than) |
-ne | 不等于(Not equal) |
判断符 | 说明 |
---|---|
-r | 有读的权限(read) |
-w | 有写的权限(write) |
-x | 有执行权限(execute) |
判断符 | 说明 |
---|---|
-f | 文件存在并且是一个常规的文件(file) |
-e | 文件存在(existence) |
-d | 文件存在并是一个目录(directory) |
# 1 > 2 ?
[root@MiWiFi-R4CM-srv myShell]# [ 1 -gt 2 ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
127
# 1 < 2 ?
[root@MiWiFi-R4CM-srv myShell]# [ 1 -lt 2 ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0
# 3-1 = 2 ?
[root@MiWiFi-R4CM-srv myShell]# [ $((3-1)) -eq 2 ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0
[root@MiWiFi-R4CM-srv myShell]# ll
-rwxrwxrwx. 1 root root 32 3月 3 13:00 hello.sh
# hello.sh 文件 是否有可写权限?
[root@MiWiFi-R4CM-srv myShell]# [ -w hello.sh ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 # 有
# hello.sh 文件 是否有可读权限?
[root@MiWiFi-R4CM-srv myShell]# [ -r hello.sh ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 # 有
# hello.sh 文件 是否有可执行权限?
[root@MiWiFi-R4CM-srv myShell]# [ -e hello.sh ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 # 有
# 查看 /home/myShell/test.txt 文件存在且是一个常规文件?
[root@MiWiFi-R4CM-srv myShell]# [ -f /home/myShell/test.txt ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 # 存在
# 查看 /home/myShell/aaa.txt 文件是否存在
[root@MiWiFi-R4CM-srv myShell]# [ -e /home/myShell/aaa.txt ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
1 # 不存在
# /home/myShell 是否为一个目录
[root@MiWiFi-R4CM-srv myShell]# [ -d /home/myShell ]
[root@MiWiFi-R4CM-srv myShell]# echo $?
0 #是目录
&& : 表示前一条命令执行成功时,才执行后一条命
|| : 表示上一条命令执行失败后,才执行下一条命令
[ condition ] && echo OK || echo NotOK
[ condition ] && [] || echo NotOK
if [ 条件判断式 ];then
# 程序代码
elif [ 条件判断式 ];then
# 程序代码
fi
# 或者
if [ 条件判断式 ]
then
# 程序代码
elif [ 条件判断式 ]
then
# ...
fi
注意:
[ 条件判断式 ],中括号和条件判断式之间必须有空格
if 后要有空格
实操案例:
a. 输入一个数字,如果输入的是1、2、3,则输出具体的数字,否则什么也输出
b. 新建一个shell文件,名称为:control_if.sh ,内容如下
#!/bin/bash
if [ $1 -eq "1" ]
then
echo "You entered the number 1"
elif [ $1 -eq "2" ]
then
echo "You entered the number 2"
fi
if [ $1 -eq "3" ];then
echo "You entered the number 3"
else
echo "You entered the other number"
fi
c. 执行control_if.sh
# 不带参数执行
[root@MiWiFi-R4CM-srv myShell]# sh controll_if.sh
controll_if.sh: 第 2 行:[: -eq: 期待一元表达式
controll_if.sh: 第 5 行:[: -eq: 期待一元表达式
controll_if.sh: 第 9 行:[: -eq: 期待一元表达式
# 执行controll_if.sh 并带参数1
[root@MiWiFi-R4CM-srv myShell]# sh controll_if.sh 1
You entered the number 1
case $变量名 in
"值1")
如果变了的值等于1,则执行程序1
;;
"值2")
如果变量的值等于2,则执行程序2
;;
........
esac
新建control_case.sh,内容如下
#!/bin/bash
case $1 in
"1")
echo "You entered the number 1"
;;
"2")
echo "You entered the number 2"
;;
esac
执行control_case.sh
[root@MiWiFi-R4CM-srv myShell]# bash control_case.sh 1
You entered the number 1
for ((初始值;循环控制条件;变量变化))
do
command1
command2
...
commandN
done
实操案例:新建一个control_for.sh,内容如下
#!/bin/bash
result=0
for((i=1;i<=100;i++))
do
result=$[$result+$i]
done
echo $result
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
实操案例:
创建shell脚本control_for_one.sh,内容如下
#!/bin/bash
# $* 任意参数(是个整体)
for i in $*
do
echo " I love $i"
done
# $@ 任意参数(逐个区分)
for j in $@
do
echo " I love $j"
done
执行shell control_for_one.sh
[root@MiWiFi-R4CM-srv myShell]# sh control_for_one.sh a b c d e
I love a
I love b
I love c
I love d
I love e
实操案例:
#!/bin/bash
# $*与$@ 不加双引号时看不出来区别
for i in $*
do
echo " I love $i"
done
for j in $@
do
echo "I love $j"
done
echo "====================================="
# $*与$@ 加双引号时区明显
for m in "$*"
do
echo "I love $m"
done
for n in "$@"
do
echo "I love $n"
done
执行结果
[root@MiWiFi-R4CM-srv myShell]# sh control_for_one.sh a b c d e
I love a
I love b
I love c
I love d
I love e
I love a
I love b
I love c
I love d
I love e
=====================================
I love a b c d e
I love a
I love b
I love c
I love d
I love e
while [条件表达式]
do
#code
done
创建control_while.sh,内容如下
#!/bin/bash
i=1
s=0
while [ $i -le 100 ]
do
s=$(($s+$i))
i=$(($i+1))
done
echo $s
执行
[root@MiWiFi-R4CM-srv myShell]# sh control_while.sh
5050
read [选项] [参数]
选项:
参数:
变量:指定读取的变量名
新建read.sh,内容如下
#!/bin/bash
read -t 10 -p "Please enter your name in ten second " NAME
echo $NAME
执行
# 10 秒内输入 aa
[root@MiWiFi-R4CM-srv myShell]# bash read.sh
Please enter your name in ten second aa
aa
# 10 秒内再输入 cc
[root@MiWiFi-R4CM-srv myShell]# cc
cc: 致命错误:没有输入文件
编译中断。
[root@MiWiFi-R4CM-srv myShell]#