shell编程全
声明: 学习视频来自B站UP主
泷羽sec,如涉及侵权马上删除文章。本文只涉及学习内容,其他的都与本人无关,切莫逾越法律红线,否则后果自负
泷羽sec的个人空间-泷羽sec个人主页-哔哩哔哩视频 微信公众号:泷羽sec
1.基本命令
1 echo命令
- `set | grep name` //查看变量
- `unset name` //删除变量,unset不能删除只读变量如readonly name,此时name无法删除
```bash
str = "hello world!"
str = 'hello world!'
declare -i num = 42
num = 42
my_array=(1 2 3 4 5) //整数索引数组
declare -A associative_array //关联数组
associative_array["name"]="John"
associative_array["age"]=30
1 printf命令
模仿 C 程序库(library)里的 printf() 程序。指定格式输出
echo "It is a test"
echo It is a test //两个都是打印字符串
echo "\"It is a test\"" //显示转义字符
read name
echo "$name It is a test" //显示变量
echo -e "OK! \n" //-e 开启转义显示换行\n
echo "It is a test"
echo -e "OK! \c" //-e 开启转义\c不换行
echo "It is a test"
echo '$name\"' //使用单引号原样输出
echo `date` //显示命令执行结果(反引号)
2.test命令
用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。
test 命令在 Unix 和类 Unix 系统中用于检查文件属性或比较字符串和整数。它是 shell 内置的命令,也可以通过 /bin/test 调用。test 命令可以用于条件语句(如 if、while、until)中,以决定是否执行特定的代码块。
数值测试
%d:十进制整数%f:浮点数%c:字符%x:十六进制数%o:八进制数%b:二进制数%e:科学计数法表示的浮点数
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876
%s %c %d %f 都是格式替代符,%s 输出一个字符串,%d 整型输出,%c 输出一个字符,%f 输出实数,以小数形式输出。%-10s 指一个宽度为10个字符(- 表示左对齐,没有则表示右对齐),任何字符都会被显示在10个字符宽的字符内,如果不足够则自动以空格填充,超过也会将内容全部显示出来。%-4.2f 指格式化为小数,其中 .2 指保留2位小数。
参数说明
-eq等于则为真-ne不等于则为真-gt大于则为真-ge大于等于则为真-lt小于则为真-le小于等于则为真
num1=100
num2=100
if test $[num1] -eq $[num2]
then
echo '两个数相等!'
else
echo '两个数不相等!'
fi
字符串测试
=等于则为真!=不相等则为真-z字符串 字符串的长度为零则为真-n字符串 字符串的长度不为零则为真
num1="ru1noob"
num2="runoob"
if test $num1 = $num2
then
echo '两个字符串相等!'
else
echo '两个字符串不相等!'
fi
文件测试
-e文件名 如果文件存在则为真-r文件名 如果文件存在且可读则为真-w文件名 如果文件存在且可写则为真-x文件名 如果文件存在且可执行则为真-s文件名 如果文件存在且至少有一个字符则为真
另外,Shell 还提供了与( -a )、或( -o )、非( ! )三个逻辑操作符用于将测试条件连接起来,其优先级为:! 最高, -a 次之, -o 最低。例如:
cd /bin
if test -e ./bash
then
echo '文件已存在!'
else
echo '文件不存在!'
fi
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
3. 永久环境变量
3.1 常见变量
将/root目录直接添加到环境变量,整个/root目录的文件都可以执行
将 /root 目录添加到当前会话的 PATH 环境变量的开头。这意味着,当你在命令行中输入一个命令时,系统会首先在 /root 目录下查找该命令,以上更改只会影响当前会话,不是永久变量
- 将脚本放入环境变量的路径。比如直接写到
/usr/bin系统级可执行文件的默认位置 - 写入配置文件
- 打开
.bashrc或.bash_profile文件,并添加环境变量设置 - 对于所有用户,可以在全局配置文件中设置环境变量
/etc/environment/etc/profile
- 打开
3.2特殊变量
设立临时变量
设立永久变量
$0:脚本名称$1, $2,$3 ....等表示脚本参数$#:传递给脚本的参数数量$?:表示上一个命令的退出状态
export PATH=/root:PATH
echo $PATH
vi .bashrc
文件末尾写入 export PATH=/root::PATH
source (变量生效,或者重启生效)
vi /etc/environment
写入 PATH="/root:$PATH"
个人用户环境变量
全局环境变量
/etc/profile.d/*.sh:
可以在 /etc/profile.d/ 目录下创建一个或多个以 .sh 结尾的脚本文件,并在其中设置环境变量。这些脚本将在 /etc/profile 被执行时被调用。
4.字符串显示
Shell 字符串
vi /etc/profile
export PATH=/usr/local/bin:$PATH //添加 /usr/local/bin 到 PATH 环境变量
source /etc/profile
echo $PATH
touch /etc/profile.d/myenv.sh
vi /etc/profile.d/myenv.sh
export PATH=/root:$PATH //写入
chmod +x /etc/profile.d/myenv.sh
source /etc/profile.d/myenv.sh
echo $PATH
5.脚本参数传递与数学运算
脚本参数传递
your_name="runoob"
str="Hello, I know you are \"$your_name\"! \n"
echo -e $str
输出:Hello, I know you are "runoob"!
str = "hello world"
echo ${#str} //输出字符串长度
echo ${str:0:6} //打印前五个字符
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4 //查找子字符i或o,谁先出现计算谁 注意是反引号`
echo 执行的文件名是:$0
echo 第一个参数是:$1
echo 第二个参数为:$2
echo 第三个参数为:$3
echo 传递的参数作为一个字符串显示:$*
echo 传递的参数独立作为每一个字符串显示:$@
echo 传递到脚本参数个数是:$#
echo 最后命令退出状态:$?
echo 脚本运行的当前进程的ID是:$$
数学运算
expr 5+10 //直接输出5+10
expr 5 + 10 //计算5 + 10
expr 10 - 5 //计算10 - 5
expr 10 \* 5 //乘法需要反斜杠转义
expr 10 / 5 //取整
expr 10 % 5 //取余
expr \(5 + 10\)\*7 //括号也需要转义
name = `expr \(5 + 10\)\*7` //这里使用的是反引号,完整的表达式要被`` 包含
echo $name
# 初始化变量
num=5
# 自增
num=$(expr $num + 1)
# 自减
num=$(expr $num - 1)
echo $num
# 初始化变量
num=5
# 自增
num=$((num + 1))
# 自减
num=$((num - 1))
echo $num
# 初始化变量
num=5
# 自增
((num++))
# 自减
((num--))
echo $num
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
数学运算
\$* 演示
for i in "$*"; do
echo $i
done
\$@ 演示
for i in "$@"; do
echo $i
done
## expr 演示
- 直接输出 `5+10`
- 计算 `5 + 10`
- 计算 `10 - 5`
- 乘法需要反斜杠转义:`10 \* 5`
- 取整:`10 / 5`
- 取余:`10 % 5`
- 括号也需要转义:`\(5 + 10\)\*7`
- 使用反引号:`name = \`expr \(5 + 10\)\*7\``
## 自增和自减
```bash
# 初始化变量
num=5
# 自增
num=$(expr $num + 1)
# 自减
num=$(expr $num - 1)
echo $num
使用 (( )) 进行运算
# 初始化变量
num=5
# 自增
num=$((num + 1))
# 自减
num=$((num - 1))
echo $num
使用 (( )) 进行自增和自减
# 初始化变量
num=5
# 自增
((num++))
# 自减
((num--))
echo $num
算术运算符
# 初始化变量
num=5
echo "初始值: $num"
# 自增
let num++
echo "自增后: $num"
# 自减
let num--
echo "自减后: $num"
# 使用 $(( ))
num=$((num + 1))
echo "使用 $(( )) 自增后: $num"
num=$((num - 1))
echo "使用 $(( )) 自减后: $num"
# 使用 expr
num=$(expr $num + 1)
echo "使用 expr 自增后: $num"
num=$(expr $num - 1)
echo "使用 expr 自减后: $num"
# 使用 (( ))
((num++))
echo "使用 (( )) 自增后: $num"
((num--))
echo "使用 (( )) 自减后: $num"
| 运算符 | 描述 |
| --- | --- |
| + | 加法 |
| - | 减法 |
| * | 乘法 |
| / | 除法 |
| % | 取余 |
| ** | 幂运算 |
| ++ | 自增 |
| -- | 自减 |
6.运算符
1. 算术运算符
假定变量 a 为 10,变量 b 为 20:
```shell
# 初始化变量
num=5
echo "初始值: $num"
# 自增
let num++
echo "自增后: $num"
# 自减
let num--
echo "自减后: $num"
# 使用 $(( ))
num=$((num + 1))
echo "使用 $(( )) 自增后: $num"
num=$((num - 1))
echo "使用 $(( )) 自减后: $num"
# 使用 expr
num=$(expr $num + 1)
echo "使用 expr 自增后: $num"
num=$(expr $num - 1)
echo "使用 expr 自减后: $num"
# 使用 (( ))
((num++))
echo "使用 (( )) 自增后: $num"
((num--))
echo "使用 (( )) 自减后: $num"
运算符说明
+加法:expr $a + $b结果为 30。-减法:expr $a - $b结果为 -10。*乘法:expr $a \* $b结果为 200。/除法:expr $b / $a结果为 2。%取余:expr $b % $a结果为 0。=赋值:a=$b把变量 b 的值赋给 a。
2. 关系运算符
假定变量 a 为 10,变量 b 为 20:
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b`
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
运算符说明
-eq检测两个数是否相等,相等返回 true:[ $a -eq $b ]返回 false。-ne检测两个数是否不相等,不相等返回 true:[ $a -ne $b ]返回 true。-gt检测左边的数是否大于右边的,如果是,则返回 true:[ $a -gt $b ]返回 false。-lt检测左边的数是否小于右边的,如果是,则返回 true:[ $a -lt $b ]返回 true。-ge检测左边的数是否大于等于右边的,如果是,则返回 true:[ $a -ge $b ]返回 false。-le检测左边的数是否小于等于右边的,如果是,则返回 true:[ $a -le $b ]返回 true。
3. 布尔运算符
假定变量 a 为 10,变量 b 为 20:
```shell
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
4. 逻辑运算符
假定变量 a 为 10,变量 b 为 20:
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
5. 字符串运算符
假定变量 a 为 “abc”,变量 b 为 “efg”:
a="abc"
b="efg"
if [ $a = $b ]
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
6. 文件测试运算符
file="/var/www/runoob/test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
7.脚本与用户交互
1. 脚本交互
## if else 的 [...] 判断语句中大于使用 -gt,小于使用 -lt。
```shell
read name age
xiaoyu 26
echo $name
echo $age
进入bash环境:
bash
读取用户输入的姓名:
read -p "请输入你的姓名:" name
指定时间自动退出:
read -p "请输入你的姓名:" name -t 10
指定输入长度:
read -n 3 -t 10 -p "请输入你的姓名:" name
读取用户输入并回显:
read -p "请输入你的姓名:" name
echo "你输入的姓名为$name"
8. 流程控制
8.1. if else 语句
if else 的 […] 判断语句中⼤于使⽤ -gt,⼩于使⽤ -lt。
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
如果使用 ((...)) 作为判断语句,大于和小于可以直接使用 > 和 <:
a=10
b=20
if (( $a == $b ))
then
echo "a 等于 b"
elif (( $a > $b ))
then
echo "a 大于 b"
elif (( $a < $b ))
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
if else 语句经常与 test 命令结合使用,如下所示:
a=10
b=20
if [ $a == $b ]
then
echo "a 等于 b"
elif [ $a -gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
if语句写成一行:
if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi
8.2. case 语句
num1=$[2*3]
num2=$[1+5]
if test $[num1] -eq $[num2]
then
echo '两个数字相等!'
else
echo '两个数字不相等!'
fi
read -p "请你输入一个数值:" num
case $num in
1)
echo 你输入的数字是1
;;
2)
echo 你输入的数字是2
;;
3)
echo 你输入的数字是3
;;
*)
echo 你输入的是其他数字
;;
esac
9. 循环控制
9.1. for循环
read -p "请你输入字符串:" site
case "$site" in
"bing")
echo "Bing 搜索"
;;
"google")
echo "Google 搜索"
;;
"baidu")
echo "百度搜索"
;;
esac
for循环执行的操作:
for num in 1 2 3 4 5
do
echo "The number is $num"
done # for循环结束关键字
使用$(seq 1 100):
for i in $(seq 1 100)
do
echo $i
done
使用C风格的for循环:
for ((i=1;i<100;i++))
do
echo $i
done
9.2. while循环
i=1
while (( $i < 100 ))
do
echo $i
((i++))
done
i=1
while (( $i <= 10 ))
do
echo $i
let "i++"
done
9.3. until循环
i=0
until [ ! $i -lt 10 ]
do
echo $i
((i++))
done
9.4. break
跳出所有循环(终止执行后面的所有循环):
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!" ;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
9.5. continue
不会跳出所有循环,仅仅跳出当前循环:
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!" ;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
10. 函数创建调用
10.1. 函数基本创建及调用
DemoFunc(){
echo "hello world"
}
DemoFunc
10.2带return的函数:
函数返回值在调用该函数后通过 $? 来获得
funWithReturn() {
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
# 函数返回值在调用该函数后通过 $? 来获得
10.3. 函数参数
带参数的函数:
DemoFunc() {
echo "hello world"
echo "My name is $1"
}
DemoFunc xiaoyu
带两个参数的函数:
DemoFunc() {
echo "hello world"
echo "My name is $1, and my age is $2 years old"
}
DemoFunc xiaoyu 27
注意,$10 不能获取第10个参数,获取第10个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
另外,还有几个特殊字符用来处理参数:
$#传递到脚本或函数的参数个数$*以一个单字符串显示所有向脚本传递的参数$$脚本运行的当前进程ID号$!后台运行的最后一个进程的ID号$@与$*相同,但是使用时加引号,并在引号中返回每个参数$-显示Shell使用的当前选项,与set命令功能相同$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
11. 脚本包含
假设存在2.sh,新建3.sh写入2.sh
然后bash 3.sh可以调用执行2.sh。
假设存在`2.sh`,可以通过`source`命令来包含执行该脚本:
2.sh:
name = "xiaoyu"
age = 23
在3.sh中可以这样使用:
source 2.sh //或者../2.sh 使⽤.来引⽤2.sh⽂件
echo "My name is $name,and I am$age years old"
bash 3.sh
12. 重定向
12.1. 输出重定向
命令说明:
command > file将输出重定向到 file。command < file将输入重定向到 file。command >> file将输出以追加的方式重定向到 file。n > file将文件描述符为 n 的文件重定向到 file。n >> file将文件描述符为 n 的文件以追加的方式重定向到 file。n >& m将输出文件 m 和 n 合并。n <& m将输入文件 m 和 n 合并。<< tag将开始标记 tag 和结束标记 tag 之间的内容作为输入。
示例:
ls > 1.txt # 将ls执行返回的内容输入重定向1.txt
who > 1.txt # 将who执行返回的内容输入重定向1.txt
可以看出 > 会覆盖1.txt内容,可以使用 >> 追加。
ls > /dev/null # 将ls重定向至回收站 执行但无回显
12.2. 输入重定向
ls -l < dirs.txt # 从dirs.txt读取内容
command1 < infile > outfile
同时替换输⼊和输出,执⾏command1,从⽂件infile读取内容,然后将输出写⼊到outfile中。
如果希望执⾏某个命令,但⼜不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
command > /dev/null
/dev/null 是⼀个特殊的⽂件,写⼊到它的内容都会被丢弃;如果尝试从该⽂件读取内容,那么什么也读
不到。但是 /dev/null ⽂件⾮常有⽤,将命令的输出重定向到它,会起到"禁⽌输出"的效果。
12.3. 文件描述符
0:标准输入1:标准输出2:错误输出
示例:
ls > 3.txt 2 > 5.txt
如果ls输出正确会输出到3.txt
coo > 3.txt 2 > 5.txt
如果coo输出错误会输出到5.txt,输出详细错误信息。
$age years old"
bash 3.sh
# 12. 重定向
## 12.1. 输出重定向
命令说明:
- `command > file` 将输出重定向到 file。
- `command < file` 将输入重定向到 file。
- `command >> file` 将输出以追加的方式重定向到 file。
- `n > file` 将文件描述符为 n 的文件重定向到 file。
- `n >> file` 将文件描述符为 n 的文件以追加的方式重定向到 file。
- `n >& m` 将输出文件 m 和 n 合并。
- `n <& m` 将输入文件 m 和 n 合并。
- `<< tag` 将开始标记 tag 和结束标记 tag 之间的内容作为输入。
示例:
```shell
ls > 1.txt # 将ls执行返回的内容输入重定向1.txt
who > 1.txt # 将who执行返回的内容输入重定向1.txt
可以看出 > 会覆盖1.txt内容,可以使用 >> 追加。
ls > /dev/null # 将ls重定向至回收站 执行但无回显
12.2. 输入重定向
ls -l < dirs.txt # 从dirs.txt读取内容
command1 < infile > outfile
同时替换输⼊和输出,执⾏command1,从⽂件infile读取内容,然后将输出写⼊到outfile中。
如果希望执⾏某个命令,但⼜不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
command > /dev/null
/dev/null 是⼀个特殊的⽂件,写⼊到它的内容都会被丢弃;如果尝试从该⽂件读取内容,那么什么也读
不到。但是 /dev/null ⽂件⾮常有⽤,将命令的输出重定向到它,会起到"禁⽌输出"的效果。
12.3. 文件描述符
0:标准输入1:标准输出2:错误输出
示例:
ls > 3.txt 2 > 5.txt
如果ls输出正确会输出到3.txt
coo > 3.txt 2 > 5.txt
如果coo输出错误会输出到5.txt,输出详细错误信息。

4231

被折叠的 条评论
为什么被折叠?



