shell编程超全!!!

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 命令可以用于条件语句(如 ifwhileuntil)中,以决定是否执行特定的代码块。

数值测试

  • %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 目录下查找该命令,以上更改只会影响当前会话,不是永久变量

  1. 将脚本放入环境变量的路径。比如直接写到/usr/bin 系统级可执行文件的默认位置
  2. 写入配置文件
    • 打开 .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,输出详细错误信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值