Shell----Shell编程快速入门

一、定义变量

1.1 定义变量的方法

在shell中定义变量使用,如

$ A=1
$ echo $A
1
$

注意:在shell中,定义变量的时候,等号前后都不能有空格,如下几种都是错误的

$ A= 1
-bash: 1: command not found
$ A =1
-bash: A: command not found
$ A = 1
-bash: A: command not found
$

1.2 取消变量

使用unset命令,如下,取消后再打印的时候就显示为空了

$ A=1
$ echo $A
1
$ unset A
$ echo $A

$

1.3 声明一个静态变量

使用readonly声明一个静态变量,一经赋值后不能修改也不能取消,只有退出当前登录,下次登录后才取消

$ readonly B=2
$ echo $B
2
$ unset B
-bash: unset: B: cannot unset: readonly variable
$ B=3
-bash: B: readonly variable
$

1.4 变量定义规则

  • 变量名称可以由字母、数字、下划线组成,但是不能以数字开头,环境变量名建议大写
  • 等号两侧不能有空格
  • 在bash中,变量默认类型都是字符串,无法直接进行数值运算
  • 变量的值如果有空格,需要使用双引号或单引号括起来
  • 将变量声明为环境变量,需要使用export声明

1.5 实例演示

(1)变量值默认是字符串,不能进行数值运算,如下所示

$ C=1+1
$ echo $C
1+1
$

(2)变量值中有空格,需要使用引号,如果不使用引号,则会报错,如下所示

$ D="hello world"
$ echo $D
hello world
$ D=hello world
-bash: world: command not found
$

(3)如下演示如何使用export声明环境变量,可以发现只有使用export声明为环境变量后,才可以在bash脚本中打印出来,否则在bash脚本中打印的变量E就是一个空

$ E="hello world"
$ echo 'echo $E'>test.sh
$ cat test.sh
echo $E
$ bash test.sh

$ export E
$ bash test.sh
hello world
$

二、特殊变量

2.1 特殊变量:$n

$n,n为数字,n为0-9,$0 代表脚本名称,$1- 9 代表第一到第九个参数, 9 以上的参数需要使用大括号,如 9代表第一到第九个参数,9以上的参数需要使用大括号,如 9代表第一到第九个参数,9以上的参数需要使用大括号,如{10}表示第10个参数,比如如下,创建test.sh脚本文件,脚本如下,即打印脚本名本身,以及第一个、第二个和第三个参数

#!/bin/bash
echo $0
echo $1
echo $2
echo $3

用如下的方式执行,可以看出符合我们的预期

$ bash test.sh hahah 2 100
test.sh
hahah
2
100
$

2.2 特殊变量 $#

$# 为获取所有输入参数的个数,如下,在test.sh脚本文件中写入如下内容,即打印参数的个数

#!/bin/bash

echo $#

使用如下命令执行,可以看出,当不输入参数时,打印的是0,当输入三个参数时则打印3

$ bash test.sh
0
$ bash test.sh 111 222 333
3
$

2.3 特殊变量$*

∗ 作用是获取命令行中所有的参数, * 作用是获取命令行中所有的参数, 作用是获取命令行中所有的参数,* 把所有的参数看成一个整体,如下test.sh代码即为打印$*的内容

#!/bin/bash

echo $*

执行结果如下,可以看出将执行时输入的三个参数都打印出来了

$ bash test.sh 111 222 333
111 222 333
$

2.4 特殊变量$@

@ 作用是这个变量代表命令行中所有的参数,不过 @ 作用是这个变量代表命令行中所有的参数,不过 @作用是这个变量代表命令行中所有的参数,不过@把每个参数区分对待,如下,在test.sh中编写代码,打印$@

#!/bin/bash

echo $@

执行结果如下,可以看出此时同样将三个参数都打印出来了

$ bash test.sh 111 222 333
111 222 333
$

2.5 特殊变量$?

$? 作用是获取最近一次执行的命令的返回状态,如果这个变量的值为0,表示上一个命令执行成功,如果这个变量不是0,则证明上个命令执行错误了

如下,当执行ls正确后, ? 的值为 0 ,而当输入一个错误的命令时,此时 ?的值为0,而当输入一个错误的命令时,此时 ?的值为0,而当输入一个错误的命令时,此时?的值是127

$ ls
test.sh
$ echo $?
0
$ lsss
-bash: lsss: command not found
$ echo $?
127
$

三、运算符

3.1 运算符的基本语法

运算符有以下三种方式:

  • $((运算式))
  • $[运算式]
  • expr 运算式

这里需要注意的是,当使用expr的时候,运算符前后必须要使用空格

运算符号就是常见的+,-,\*,/,%,即加减乘除,其中需要注意的是乘法不是星号,而是带反斜线的*

3.2 运算符实例演示

(1) 使用 $((运算式)) 方式,此时运算符前后有没有空格是都可以的,而且此时的乘法就是*号

$ A=$((2+3))
$ echo $A
5
$ A=$(( 2 + 3 ))
$ echo $A
5
$ A=$(( 3+2 ))
$ echo $A
5
$ A=$(( 3-2 ))
$ echo $A
1
$ A=$((3*2))
$ echo $A
6
$ A=$((3\*2))
-bash: 3\*2: syntax error: invalid arithmetic operator (error token is "\*2")
$ A=$((3/2))
$ echo $A
1
$ A=$((3%2))
$ echo $A
1
$

(2) 使用$[运算式]的格式,可以看出,这种方式相对要求比较宽松,运算符前后有没有空格都是可以的

$ A=$[3+2]
$ echo $A
5
$ A=$[ 3+2 ]
$ echo $A
5
$ A=$[ 3 + 2 ]
$ echo $A
5
$ A=$[ 3 - 2 ]
$ echo $A
1
$ A=$[3*2]
$ echo $A
6
$ A=$[ 3 /2]
$ echo $A
1
$ A=$[ 3% 2]
$ echo $A
1
$

(3) expr 表示式,运算符号前后必须有空格,此外乘号需要加反斜线,如下:

$ expr 3+2
3+2
$ expr 3 +2
expr: syntax error
$ expr 3+ 2
expr: syntax error
$ expr 3 + 2
5
$ expr 3 - 2
1
$ expr 3 * 2
expr: syntax error
$ expr 3 \* 2
6
$ expr 3 / 2
1
$ expr 3 % 2
1
$

(4) 混合运算时的用法如下,可以发现使用expr的方式相对要复杂一点,另外两种方式相对比较简单

$ A=$(((3+2)*4))
$ echo $A
20
$ A=$[(3+2)*4]
$ echo $A
20
$ expr `expr 3 + 2 ` \* 4
20
$

四、条件判断

4.1 基本语法

[ condition ] 这里需要注意的是condition前后要有一个空格,条件非空即为true,比如 [ xxx ] 返回true,[] 则返回 false

4.2 常用判断条件

(1) 两个整数之间比较

  • = 字符串比较
  • -lt 小于
  • -le 小于等于
  • -eq 等于
  • -gt 大于
  • -ge 大于等于
  • -ne 不等于

(2) 按照文件权限进行判断

  • -r 有读的权限(read)
  • -w 有写的权限(write)
  • -x 有执行权限(execute)
    (3) 按照文件类型进行判断
  • -f 文件存在并且是一个常规的文件
  • -e 文件存在
  • -d 文件存在并是一个目录

4.3 条件判断使用举例

(1) 比较两个数的大小,如下,当返回值为0为true,否则当返回值为1则为false,此外,当放括号与数字之间必须要有空格

$ [3 -gt 2]
-bash: [3: command not found
$ [ 3 -gt 2 ]
$ echo $?
0
$ [ 3 = 2 ]
$ echo $?
1
$ [ 3 -lt 2 ]
$ echo $?
1
$ [ 3 -ne 2 ]
$ echo $?
0
$ [ 3 -eq 3 ]
$ echo $?
0
$

(2) 判断文件类型以及是否存在

$ mkdir demo
$ ls
demo  test.sh
$ [ -f test.sh ]
$ echo $?
0
$ [ -d demo ]
$ echo $?
0
$ [ -d test.sh ]
$ echo $?
1
$ [ -f demo ]
$ echo $?
1
$ [ -e test.sh ]
$ echo $?
0
$ [ -e demo ]
$ echo $?
0
$ [ -e hahahaha ]
$ echo $?
1
$

(3) 判断文件权限的条件,如下

$ ls -l
total 4
drwxrwxr-x. 2 honghua honghua  6 Jul  7 13:23 demo
-rw-rw-r--. 1 honghua honghua 21 Jul  6 16:52 test.sh
$ [ -r test.sh ]
$ echo $?
0
$ [ -w demo ]
$ echo $?
0
$ [ -x test.sh ]
$ echo $?
1
$ [ -x demo ]
$ echo $?
0
$

4.4 多条条件判断语句的逻辑关系

  • && 表示前一条命令执行成功时,才执行后一条命令,如果前一条命令失败了,则不会执行后一条命令
  • || 表示上一条命令执行失败时,才执行下一条命令,如果前一条命令成功了,则不会执行后一套命令

如下,其中test.sh为文件,demo为目录

$ [ 3 -gt 2 ] && [ -f test.sh ]
$ echo $?
0
$ [ -e test.sh ] && [ -x test.sh ]
$ echo $?
1
$ [ -d test.sh ] || [ -d demo ]
$ echo $?
0
$

五、流程控制

5.1 if 语句

5.1.1 if 语句的基本语法格式

(1) 第一种格式

if[ 条件判断式 ];then
	程序
fi

(2) 第二种格式

if[ 条件判断式 ]
    then
	    程序
fi

注意事项:

  • [ 条件判断式 ] 方括号与条件判断表达式之间必须有空格
  • if后要有空格

5.1.2 if 语句实例

如下,判断第一个参数是不是1或者2的if判断

#!/bin/bash

if [ $1 -eq 1 ];then
    echo "first is 1"
elif [ $1 -eq 2 ];then
    echo "first is 2"
else
    echo "first is not 1 and 2"
fi

当然then也可以单独放一行,如下

#!/bin/bash

if [ $1 -eq 1 ]
then
    echo "first is 1"
elif [ $1 -eq 2 ]
then
    echo "first is 2"
else
    echo "first is not 1 and 2"
fi

执行调试结果如下:

$ bash test.sh 1
first is 1
$ bash test.sh 2
first is 2
$ bash test.sh 3
first is not 1 and 2
$

5.2 case语句

5.2.1 case语句的基本语法

case $变量名 in
  "值1")
      如果变量的值扥估值1,则执行程序1
	  ;;
  "值2")
      如果变量的值等于值2,则执行程序2
	  ;;
  *)
	  如果变量的值都不是以上的值,则执行此程序
	  ;;
esac

注意事项:
(1) case行尾必须为单词 “in”, 每个模式匹配必须以有括号 ")"结束
(2)双分号 ";;"表示命令序列结束,相当于其他语言中的break
(3) 最后的 “*)” 表示默认模式,相当于其他语言中的default

5.2.2 case语句实例

如下,判断第一个参数是否为1或2

#!/bin/bash

case $1 in
    1)
        echo "num is 1"
    ;;
    2)
        echo "num is 2"
    ;;
    *)
        echo "num is not 1 and 2"
    ;;
esac

执行结果如下:

$ bash test.sh 1
num is 1
$ bash test.sh 2
num is 2
$ bash test.sh 3
num is not 1 and 2
$

5.3 for 循环

5.3.1 for 循环基本语法

for (( 初始值;循环控制条件;变量变化 ))
do
    程序
done

5.3.2 for 循环语句实例

(1)如下为计算1-100求和

#!/bin/bash

sum=0

for(( i=1;i<=100;i++ ))
do
  sum=$[$sum+$i]
done

echo $sum

执行结果如下:

$ bash test.sh
5050
$

(2) 打印所有输入的参数

#!/bin/bash

for i in $*
do
  echo $i
done

执行结果如下:

$ bash test.sh 111 222 333 444 555
111
222
333
444
555
$

(3)如下为 $* 和 $@ 的区别

#!/bin/bash

for i in $@
do
  echo $i
done

echo ----------------------------

for i in $*
do
  echo $i
done

echo ----------------------------
echo ----------------------------

for i in "$@"
do
  echo $i
done

echo ----------------------------

for i in "$*"
do
  echo $i
done

执行结果如下,可以看出,在不加引号的情况下,两者循环遍历的时候是相同的,但是当加了双引号后,两者在遍历的时候就不一样了,$*表示的是一个字符串

$ bash test.sh 111 222 333
111
222
333
----------------------------
111
222
333
----------------------------
----------------------------
111
222
333
----------------------------
111 222 333
$

5.4 while循环

5.4.1 while循环基本语法

while[ 条件判断式 ]
do
  程序
done

5.4.2 while循环语句实例

(1)如下为计算1-100之和

#!/bin/bash

i=1
sum=0
while [ $i -le 100 ]
do
  sum=$[$sum + $i ]
  i=$[$i + 1]
done

echo $sum

执行结果如下:

$ bash test.sh
5050
$

六、read读取控制台输入

6.1 基本语法

read(选项)(参数)

选项:
  -p:指定读取值时的提示符
  -t:指定读取值时等待的时间(秒)
  
参数:
   变量:指定读取值的变量名

6.2 read读取控制台输入实例

(1) 如下输入用户名的实例

#!/bin/bash


read -p "please input username: " username

echo $username

执行结果如下:

$ bash test.sh
please input username: redrose2100
redrose2100
$

七、函数

7.1 系统函数

7.1.1 basename 获取文件的文件名

(1) 如下为获取文件的文件名

$ basename demo/test.txt
test.txt
$

(2) 如下可以通过指定后缀将后缀去掉

$ basename demo/test.txt .txt
test
$

7.1.2 dirname获取文件的绝对路径

如下,通过指定文件的绝对路径,从而可以获得文件的绝对路径

$ dirname /home/honghua/demo/test.txt
/home/honghua/demo
$

7.2 自定义函数

7.2.1 函数定义基本语法

[ function ] functionname[()]
{
	Action;
	[return int;]
}

注意点
(1) 必须在调用函数地方之前,先声明函数,shell脚本是逐行运行,不会像其他语言一样先编译
(2) 函数返回值,只能通过$?系统变量获得,可以显示加return语句,如果不加默认将最后一条命令运行结果作为返回值返回

7.2.2 自定义函数实例

如下为求两个数的和,这里需要注意虽然说function可以省略,但是建议写上去,可读性更好,此外函数名后面的小括号也是选填的,同样也是建议写上去,作为代码,可读性也是一个很重要的方面

#!/bin/bash


function sum()
{
   sum=0;
   sum=$[$1+$2]
   echo $sum
}

read -p "please input your param1: " p1
read -p "please input your param2: " p2

sum $p1 $p2

执行结果如下:

$ bash test.sh
please input your param1: 10
please input your param2: 20
30
$

八、Shell的工具

8.1 cut

cut的作用就是从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出

8.1.1 cut 基本语法

cut [选项参数] filename
其中常用的选项参数如下:

  • -f 列号,提取第几列
  • -d 分隔符,按照指定分析分隔符割裂

8.1.2 cut 实用举例

准备一个demo.txt文件,内容如下:

name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man

(1) 获取第一列

$ cut -d " " -f 1 demo.txt
name
zhangsanfeng
quchuji
zhoubotong
$

(2)获取第1,2列

$ cut -d " " -f 1,2 demo.txt
name age
zhangsanfeng 100
quchuji 99
zhoubotong 101
$

(3)获取zhangsanfeng的年龄

$ cat demo.txt |grep zhangsanfeng |cut -d " " -f 2
100
$

(4)取第二列及以后的列

$ cut -d " " -f 2- demo.txt
age sex
100 man
99 man
101 man
$

8.2 sed

8.2.1 sed 基本语法

sed [选项参数] ‘command’ filename
其中参数:

  • -e 直接在指令列模式上进行sed的动作编辑

命令:

  • a 新增,a的后面可以接字符串,在下一行出现
  • d 删除
  • s 查找并替换

8.2.2 sed 常用举例

首先准备测试文件demo.txt,内容如下:

name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man

(1)在第二行下面增加 zhangwuji 98 man,操作如下,可以看出如果不使用重定向是不会修改源文件的内容的

$ sed "2a zhangwuji 98 man" demo.txt
name age sex
zhangsanfeng 100 man
zhangwuji 98 man
quchuji 99 man
zhoubotong 101 man
[honghua@honghua-centos-01 demo]$ cat demo.txt
name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man
[honghua@honghua-centos-01 demo]$

(2)删除包含quchuji的行,可以看到,此时也不会修改源文件额内容

$ sed "/quchuji/d" demo.txt
name age sex
zhangsanfeng 100 man
zhoubotong 101 man
[honghua@honghua-centos-01 demo]$ cat demo.txt
name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man
[honghua@honghua-centos-01 demo]$

(3) 将每行匹配到的第一个n替换为N,如下,此时不使用g即可

$ sed "s/n/N/" demo.txt
Name age sex
zhaNgsanfeng 100 man
quchuji 99 maN
zhoubotoNg 101 man
$ cat demo.txt
name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man
$

如果使用g,则可以将所有匹配内容替换,如下:

$ sed "s/n/N/g" demo.txt
Name age sex
zhaNgsaNfeNg 100 maN
quchuji 99 maN
zhoubotoNg 101 maN
[honghua@honghua-centos-01 demo]$ cat demo.txt
name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man
[honghua@honghua-centos-01 demo]$

(4) 同时执行多条sed命令,如下,删除第二行同时将所有的n替换为N,如下:

$ sed -e "2d" -e "s/n/N/g" demo.txt
Name age sex
quchuji 99 maN
zhoubotoNg 101 maN
$ cat demo.txt
name age sex
zhangsanfeng 100 man
quchuji 99 man
zhoubotong 101 man
$

8.3 awk

8.3.1 awk 基本语法

awk [选项参数] ‘pattern{action1} pattern2{action2} …’ filename
其中:

  • pattern:表示awk在数据中查找的内容,就是匹配模式
  • action:在找到匹配内容时所执行的一系列命令

选项:

  • -F 指定输入文件拆分分隔符
  • -v 赋值一个用户定义变量

8.3.2 awk 常用实例

(1) 数据准备,将 /etc/password 文件的内容重定向到当前目录下的password文件中,如下:

sudo cat /etc/passwd >> password

(2) 使用冒号分隔,取以root开头行的分隔后的第七列

其中以root开头的行尾:

root:x:0:0:root:/root:/bin/bash

执行的命令及结果如下:

$ awk -F : '/^root/ {print $7}' password
/bin/bash
$

(3) 使用冒号分隔,取以root开头行的分隔后的第七列

$ awk -F : '/^root/ {print $1,$7}' password
root /bin/bash
$

(4) 只显示password的第一列和第七列,以逗号分隔,且在所有的行前面添加列名 user,shell,在最后一行增加“admin,/bin/bash”
如下:

$ awk -F : 'BEGIN{print "user,shell"} {print $1,$7} END{print "admin,/bin/bash"}' password
user,shell
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
adm /sbin/nologin
lp /sbin/nologin
sync /bin/sync
shutdown /sbin/shutdown
halt /sbin/halt
mail /sbin/nologin
operator /sbin/nologin
games /sbin/nologin
ftp /sbin/nologin
nobody /sbin/nologin
systemd-network /sbin/nologin
dbus /sbin/nologin
polkitd /sbin/nologin
sshd /sbin/nologin
postfix /sbin/nologin
jiayi /bin/bash
jenkins /bin/false
gitlab-runner /bin/bash
tss /sbin/nologin
avahi /sbin/nologin
admin,/bin/bash
$

(5) 所有的第三列的值加1

$ awk -F : -v i=1 '{print $3+i}' password
1
2
3
4
5
6
7
8
9
12
13
15
100
193
82
1000
75
90
1001
999
1003
60
71
$

新书上市 : Pytest 企业级应用实战

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

redrose2100

您的鼓励是我最大的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值