【Linux之·shell编程】

系列文章目录



前言

  Shell编程是一门非常有用的技能,无论你是一名系统管理员、开发人员还是普通用户。通过学习Shell编程,你可以轻松地自动化许多重复繁琐的任务,优化你的工作流程,提高工作效率。本文将介绍学习Shell编程的必要性以及如何开始学习Shell编程。无论你是初学者还是有一定经验的Shell编程者,本文都将对你有所帮助。


一、概述

1.shell的定义

  Shell是一种命令行解释器,是在计算机操作系统中提供用户与操作系统交互的一种方式。通常Shell是指命令行界面,用户通过Shell界面可以输入命令并获得相应的操作结果。

2.shell的主要功能

(1)提供命令行界面:Shell提供了一个命令行界面,用户可以通过键盘输入命令来与操作系统进行交互。这种交互方式相对于图形用户界面更加高效,可以让用户快速地完成各种操作。
(2)管理文件和目录:Shell可以对文件和目录进行各种操作,如创建、删除、复制、移动、重命名等等。用户可以通过Shell在文件系统中进行各种操作,例如创建文件夹、查看文件内容、修改文件权限等。
(3)执行各种命令和程序:用户可以通过Shell执行各种命令和程序,如编译代码、运行脚本、启动服务等。Shell会将用户输入的命令解释并执行相应的操作。
(4)管理进程和系统资源:Shell可以管理和控制进程,包括启动、停止、暂停和重启进程,还可以查看和管理当前正在运行的进程。同时,Shell还可以管理系统资源,如内存、CPU等。
(5)配置系统和环境:Shell可以管理和配置系统设置、环境变量、网络配置等等。用户可以通过Shell配置网络连接,修改系统环境变量等等。

3.shell常见的解释器

解释器:一种命令解释器,主要作用是对命令进行运行和解释,将需要执行的操作传递给操作系统内核并执行

四种解释器:
#!/bin/bash(默认)
#!/bin/ksh
#!/bin/bsh
#!/bin/sh

注意: shell脚本运行不一定需要解释器,有些脚本没有解释器也可以运行

4.shell脚本文件权限与脚本执行

  • 执行shell脚本的方法:
方法一:sh 文件名
方法二:bash 文件名
方法三:./文件名
方法四:source 文件名 

注意: 文件创建默认是没有执行权限的,所以要给加上权限:chmod u+x sh结尾的文件。

5.错误处理与调试

5.1错误处理与调试

  • 在Bash中,常见的错误包括语法错误、运行时错误和逻辑错误。

5.1.1语法错误

语法错误通常是指脚本中出现了不符合 Bash 语法规范的语句,例如缺少引号、括号不匹配、变量名错误等等。这些错误会导致脚本无法正常执行。为了避免语法错误,可以使用 ShellCheck 等工具来检查代码。

5.1.2运行时错误

运行时错误通常是指脚本在执行过程中出现了问题,例如文件不存在、权限不足、内存不足等等。为了避免这些错误,可以在脚本中使用条件语句进行判断,以确保程序能够正确地运行。同时,还可以使用 try-catch 或者 trap 命令来捕捉和处理异常。

5.1.3逻辑错误

逻辑错误通常是指脚本的输出结果和预期不一致,例如变量赋值错误、循环条件错误、函数调用错误等等。为了避免逻辑错误,可以在编写脚本时进行严格的测试和校验,以确保程序的正确性。

5.2调试技巧与工具

5.2.1

  • 在 Bash 中,可以使用 echo 命令输出调试信息来查看程序的执行情况。

5.2.2使用set命令

  • 在 Bash 中,可以使用 set -x 命令来打开调试模式,这样所有执行的语句都会被输出到终端上。

示例:

#!/bin/bsh

testfunc1() {
    echo this is testfunc1!
}

set -x
testfunc1
set +x

运行结果:
在这里插入图片描述

5.2.3使用调试器

Bash 提供了内置的调试器——bashdb,它可以帮助我们更方便地调试 Bash 脚本。

首先需要安装 bashdb,例如在 Ubuntu 系统上可以使用以下命令进行安装:

sudo apt-get install bashdb

然后在脚本文件中添加以下代码:

#!/bin/bsh -x

testfunc1() {
    echo this is testfunc1!
}

testfunc1

最后运行以下命令即可进入调试模式:

bashdb script.sh

在调试模式下,可以使用类似 gdb 的命令来逐步执行脚本、查看变量值等等。
示例:


二、变量与符号

1.常用变量

  • =:等于号赋值,a=15
  • $a:调取a变量的值
  • ${a}:调取a变量的值,当{a}后面有其他字符时,不会影响a的获取
  • $?:判断上一条命令执行的结果,成功为0,失败为1
  • $1-$9:返回对应的第几个参数
  • $*:返回所有的参数的值是什么
  • $#:返回参数的个数
  • $?:显示上一条命令执行的结果,0表示执行成功,1或大于1表示执行失败
  • $$: Shell本身的PID(ProcessID,即脚本运行的当前进程ID号)

2.常用符号

  • >   #输出重定向(覆盖)
  • >>   #输出重定向(追加)
  • ;   #执行多条命令
  • |   #管道符
  • &&  #前一条命令执行成功才会执行后面
  • ||   #前一条命令执行失败才会执行后面
  • “”   #输出变量识别通配符
  • ‘’   #输出本身
  • ``   #优先执行,放在``中会识别成命令执行
  • &>/dev/null   #错误输出到无底洞

3.算术运算符及linux中的计算器

  expr是一个用于计算表达式的命令行工具。它可以用于执行各种数学运算,比较和字符串操作。

3.1计算两个整数的和

expr 5 + 3 # 输出:8
方式一:expr $a + $b
方式二:echo $[a + b]
方式三:echo $((a + b))

3.2计算两个整数的差

expr 5 - 3 # 输出:2
方式一:expr $a - $b
方式二:echo $[a - b]
方式三:echo $((a - b))

3.3计算两个整数的积

expr 5 \* 3 # 输出:15
方式一:expr $a \* $b
方式二:echo $[a * b]
方式三:echo $((a * b))

3.4计算两个整数的商

expr 6 / 3 # 输出:2
方式一:expr $a / $b
方式二:echo $[a / b]
方式三:echo $((a / b))

3.5整数求余

方式一:expr $a % $b
方式二:echo $[a % b]
方式三:echo $((a % b))

3.6比较两个整数是否相等

expr 5 = 3 # 输出:0

3.7比较两个整数是否不相等

expr 5 != 3 # 输出:1

3.8获取字符串的长度获取字符串的长度

expr length "hello world" # 输出:11

3.9查找字符串中某个字符的位置(第一次出现的位置)

expr index "hello world" o # 输出:5

3.10 1.2+1.3 保留两位小数

借助bc计算器,保留多少为小数可以通过sacle,但是scale只对除法,取余数,乘法有效,对加减无效

示例:

 echo "scale=2;(1.2 + 1.2)/1" | bc

运行结果:
在这里插入图片描述

4.条件判断

  • 语法:[ 判断表达式 ]

4.1文件夹或者路径

-e:目标是否存在(exist)
-d:是否为目录(directory)
-f:是否为文件(file)

示例:
在这里插入图片描述

4.2权限

-r:是否有读权限(read)
-w:是否有写入权限(write)
-x:是否有执行权限(excute)

示例:
在这里插入图片描述

4.3整形数值比较

-eq:等于(equals)
-ne:不等于(not equals)
-gt:大于(greater than)
-lt:小于(lesser than)
-ge:大于或等于(greater or equal)
-le:小于或等于(lesser or equal)

示例:
在这里插入图片描述

4.4浮点型判断

[ `echo '1.4 < 1.6' | bc` -eq 1 ] && echo "YES" 

示例:
在这里插入图片描述

4.4字符串判断

=:相等
!=:不相等

示例:
在这里插入图片描述

三、语法

1.输入与输出语句

1.1输入

  • 语法:read -参数
-p:给出提示符,默认不支持”\n“换行
-s:隐藏输入的内容
-t:给出等待的时间,超出会推出read
-n:限制读取字符串的个数,触发时到临界的值会自动执行
-r:允许用户输入特殊字符,如 空格、/、\、?等
-a:赋值数组
-u:从给定文件描述符(fd=N)中读取数据
-d:表示delimiter,即定界符
-e:只用于互相交互的脚本,它将readline用于收集输入行

1.2输出

  • 字体色范围:30-37
echo -e "\033[30m 黑色字 \033[0m"
echo -e "\033[31m 红色字 \033[0m"
echo -e "\033[32m 绿色字 \033[0m"
echo -e "\033[33m 黄色字 \033[0m"
echo -e "\033[34m 蓝色字 \033[0m"
echo -e "\033[35m 紫色字 \033[0m"
echo -e "\033[36m 天蓝字 \033[0m"
echo -e "\033[37m 白色字 \033[0m"
  • 字背景颜色范围:40-47
echo -e "\033[40;37;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[41;30;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[42;34;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[43;34;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[44;30;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[45;30;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[46;30;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[47;34;5m 我们一起晒月亮!!! \033[0m"
echo -e "\033[41;30;5m 我们一起晒月亮!!! \033[0m"
  • 特效
echo -e "\033[0m 无任何特效 \033[0m"
echo -e "\033[1m 高亮度 \033[0m"
echo -e "\033[4m 下划线 \033[0m"
echo -e "\033[5m 闪烁 \033[0m"
echo -e "\033[7m 反显 \033[0m"
echo -e "\033[8m 消隐 \033[0m"
echo -e "\033[nA 光标上移n行 \033[0m"
echo -e "\033[nB 光标下移n行 \033[0m"
echo -e "\033[nC 光标右移n字符 \033[0m"
echo -e "\033[nD 光标左移n字符 \033[0m"
echo -e "\033[y;xH 设置光标位置 \033[0m"
echo -e "\033[2J 清屏 \033[0m"
echo -e "\033[K 清除从光标到行尾的内容 \033[0m"
echo -e "\033[s 保存光标位置 \033[0m"
echo -e "\033[u 恢复光标位置 \033[0m"
echo -e "\033[?25l 隐藏光标 \033[0m"
echo -e "\033[?25h 显示光标 \033[0m"

2.循环控制语句

2.1 if循环控制(单分支与多分支)

2.1.1单个判断

语法:

if [ 执行条件 ]
then
执行语句
fi
2.1.2单个判断带else

语法:

if [ 执行条件 ]
then
执行语句
else
执行语句
fi
2.1.3多个判断

语法:

if [ 执行条件 ]
then
执行语句
elif [ 执行条件 ]
执行语句
.....
fi

2.2 for循环控制

语法1:

for 变量名 in 值1 值2 值3 ....
do
执行语句
done

语法2:

for i in {1..5}
do
echo $i
done

不同命令解释器的执行效果:
在这里插入图片描述

注意: 从 ubuntu 6.10 开始,ubuntu 就将先前默认的bash shell 更换成了dash shell;其表现为 /bin/sh 链接倒了/bin/dash而不是传统的/bin/bash。在ubuntu下打印:echo $SHELL 输出bash,会误导人。

dash不支持这种C语言格式的for循环写法。

解决办法:

1、将默认shell更改为bash。(bash支持C语言格式的for循环)
  sudo dpkg-reconfigure dash
  在选择项中选No
2、直接使用bash检测:
  bash -n xxx.sh
3、为了确保shell脚本的可移植性,直接更改shell脚本,使用shell支持的for循环格式:
  for a in seq $num

语法3:

for((初值;条件;步长))
do 
   命令序列
done

2.3 while循环控制

语法:

while [ 执行条件 ]
do
执行语句
done

2.4 case循环控制

语法:

case 变量 in
值1)
执行动作1
;;
值2)
执行动作2
;;
值3)
执行动作3
;;
....
esac

3.函数与模块化

3.1 函数的定义与调用

函数定义

  • 在Bash中,可以使用“function”关键字或者省略关键字的方式来定义函数。

示例:

#使用 function 关键字定义函数]
function functest1 {
    echo this is test1
}

#省略 function 关键字
functest2() {
    echo this is test2
}

函数调用

  • 函数调用时需要使用函数名和参数列表,参数之间用空格分隔。

示例:

functest1

functest2

3.2 函数参数与返回值

传递参数

  • 在Bash中,可以通过位置变量来传递参数。例如,$1 表示第一个参数,$2 表示第二个参数,以此类推。
  • 在函数内部也可以使用特殊变量 $@ 或 $* 来获取所有传递的参数。

示例:

function functest1 {
    echo $1 $2 !
}
functest2() {
    echo Arguments:$@
}

functest1 Hello World
functest2 one two three

返回值

  • 在Bash中,函数返回值可以使用“return”命令来设置,返回值为一个非负整数。

示例:

functest2() {
    echo Arguments:$@
    return 9
}

functest2 one two three
echo functest2 return $?

3.3 模块化编程

脚本分离

  • 在Bash中,可以将脚本分解成多个文件,以实现模块化编程。
    示例:
# 文件名:libfunc.sh
#!/bin/bsh

testfunc1() {
    echo this is testfunc1!
}
-----------------------------------
# 文件名:main.sh
#!/bin/ksh

source libfunc.sh
testfunc1

运行结果:
在这里插入图片描述

模块导入与使用

  • 在Bash中,可以通过“source”或“.”命令来导入其他脚本或库文件。
source libfunc.sh

或者

. libfunc.sh

这样就可以在当前脚本中使用被导入脚本中定义的函数和变量了。

四、示例

1.常用变量

示例:

#!/bin/sh 
echo 当前执行的脚本为:$0
echo 第一个参数:$1
echo 第二个参数:$2
echo 第三个参数:$3
echo 第四个参数:$4                                                                    
echo 输入参数总个数:$# 
echo 输入的所有参数为:$*

运行符号:
在这里插入图片描述

2.常用符号

示例:

 echo ls:`ls` #``括起来, 表示里面需要执行的是命令。Shell可以先执行``中的命令,将输出结果暂时保存,在适当的地方输出。

运行结果:
在这里插入图片描述

3.语法

3.1输入与输出

3.1.1输入

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.1.2输出

示例1:
在这里插入图片描述
示例2:
在这里插入图片描述

3.2循环控制语句

3.2.1 if循环控制(单分支与多分支)

示例1:

#!/bin/bash

count=0

while [ $count -lt 5 ]
do
    if [ $count -eq 3 ]
    then
        echo -e "\033[31m$count\033[0m"
    else
        echo -e "\033[32m$count\033[0m"
    fi
    count=$((count + 1))
done

运行结果:
在这里插入图片描述

3.2.2 for循环控制

示例1:

#!/bin/sh

for i in 1 2 3 4 5 6
do
    echo  $i
done

运行结果:
在这里插入图片描述
示例2:

#!/bin/sh

for i in {1..10..2}
do
echo $i
done

运行结果:
在这里插入图片描述

示例3:

#!/bin/sh

for((i=0;i<=10;i++))
do
    echo $i
done

运行结果:
在这里插入图片描述

3.2.3 while循环控制

示例1:

#!/bin/bash

count=0

while [ $count -lt 5 ]
do
    if [ $count -eq 3 ]
    then
        echo -e "\033[31m$count\033[0m"
    else
        echo -e "\033[32m$count\033[0m"
    fi
    count=$((count + 1))
done

运行结果:
在这里插入图片描述

3.2.4 case循环控制

示例1:

#!/bin/sh

case $1 in
1)
echo this is 1!
;;
2)
echo this is 2!
;;
*)
echo this is default
;;
esac

运行结果:
在这里插入图片描述
示例2:

# 文件名:test.sh
#!/bin/bash

. output.sh
print $1 $2 $3 $4 $5 $6 $7 $8 $9
---------------------------------
# 文件名:output.sh
#!/bin/bash

print() {
    case $# in
    4)
    echo -e "\033[$2;$3;${4}m$1 \033[0m"
    ;;
    5)
    echo -e "\033[$2;$3;$4;${5}m$1 \033[0m"
    ;;
    6)
    echo -e "\033[$2;$3;$4;$5;${6}m$1 \033[0m"
    ;;
    7)
    echo -e "\033[$2;$3;$4;$5;$6;${7}m$1 \033[0m"
    ;;
    8)
    echo -e "\033[$2;$3;$4;$5;$6;$7;${8}m$1 \033[0m"
    ;;
    9)
    echo -e "\033[$2;$3;$4;$5;$6;$7;$8;${9}m$1 \033[0m"
    ;;
    *)
    echo -e "\033[$2;$3;$4;$5;0m$1 \033[0m"
    ;;
    esac
}

运行结果:
在这里插入图片描述


总结

  总之,学习Shell编程可以为我们的工作和生活带来许多便利和效益。虽然需要一定的时间和精力投入,但是一旦掌握了这门技能,我们就可以更加高效地完成各种任务,提高自己的竞争力和职业发展前景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值