【Linux命令行与Shell脚本编程】第十一章 构建基础脚本

本文介绍了如何构建基础的LinuxShell脚本,包括编写脚本文件、使用变量、显示消息、重定向输入输出以及执行数学运算。重点讲解了命令行中的命令组合、脚本文件格式、echo命令、变量(环境变量与用户自定义变量)、命令替换以及输入输出重定向的基本用法。
摘要由CSDN通过智能技术生成

Linux命令行与Shell脚本编程

第十一章 构建基础脚本



一,构建基础脚本

1,使用多个命令 ;

shell脚本的关键是 能够输入多个命令并处理每个命令的结果,也可以将一个命令的结果传给另一个命令。
shell可以让将多个命令串联起来,一次性执行完。
; 分割多个命令
    $ date ; who

2,创建shell脚本文件

2.1,格式

将shell命令放到文本文件中,
首先要用文本编辑器创建一个文件,然后在其中输入命令。
在创建shell脚本文件时,在文件的第一行指定要使用的shell,
    #!/bin/bash
在普通的shell脚本中, #用作注释行。
shell并不会处理shell脚本中的注释行。
shell脚本文件的第一行是个例外,#后面的惊叹号会告诉shell用哪个shell来运行脚本。
每行末尾加一个换行符。
    #!/bin/bash
    # This script displays the date and who's logged on
    date
    who
可以根据需要,使用分号将两个命令放在一行中,在shell脚本中,可以将命令放在独立的行中。shell会根据命令在文件中出现的顺序进行处理。

2.2,运行

路径:
        $ test1
        bash: test1: command not found
    让 bash shell找到你的脚本文件。shell会通过PATH环境变量来查找命令。
    PATH环境变量被设置为用于在其中查找命令的一系列目录。
        $ echo $PATH
        /usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/usr/bin
        :/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/user/bin $
    要让shell找到脚本,可以采用下列两种方法之一:
        ·将放置shell脚本文件的目录添加到PATH环境变量中;
        ·在命令行中使用绝对路径或相对路径来引用shell脚本文件。
权限:
        $ ./test1
        bash: ./test1: Permission denied
    在创建test1文件时,umask的值决定了新文件的默认权限设置。由于umask变量被设为022,因此新建的文件仅 文件属主和属组有读/写权限。(参见: 七,Linux文件权限)
    通过chmod命令赋予 文件属主 执行文件的权限:
        $ chmod u+x test1
        $ ./test1
            Mon Jun 01 15:38:19 EST 2020
            Christine tty2        2020-06-01 15:26

3,显示消息 echo

大多数shell命令会产生自己的输出,这些输出会显示在脚本所运行的控制台显示器上。
可以通过 echo命令后面加上字符串 来显示字符串
    $ echo This is a test
    This is a test
默认情况下,无须使用引号将要显示的字符串划定出来。如果在字符串中使用引号,则有时会比较麻烦:
    $ echo Let's see if this'll work
    Lets see if thisll work
可用单引号或双引号来划定字符串。如果在字符串中要用到某种引号,可以使用另一种引号来划定字符串:
    $ echo "Let's see if this'll work"
    Let's see if this'll work
字符串和命令输出显示在同一行中,可以使用echo命令的-n选项。
    echo -n "The time and date are: "
    
    $ ./test1
        The time and date are: Mon Jun 01 15:42:23 EST 2020

4,使用变量

在shell命令中使用其他数据来处理信息。这可以通过变量来实现。变量允许在shell脚本中临时存储信息,以便同脚本中的其他命令一起使用。

4.1,环境变量 $

用set命令显示一份完整的当前环境变量列表
在脚本中,可以在环境变量名之前加上$来引用环境变量.
    $ cat test2
        #!/bin/bash
        # display user information from the system.
        echo "User info for userid: $USER"
        echo UID: $UID
        echo HOME: $HOME
    $ chmod u+x test2
    $ ./test2
        User info for userid: Samantha
        UID: 1001
        HOME: /home/Samantha
echo命令中的环境变量会在脚本运行时被替换成当前值。
在第一个字符串中可以将 $USER系统变量放入双引号中,shell依然能够知道意图。但存在一个问题:
    $ echo "The cost of the item is $15"
        The cost of the item is 5
只要脚本在双引号中看到$,就会以为在引用变量。脚本会尝试显示变量$1的值,再显示数字5。
要显示$,必须在前面放置一个反斜线:反斜线允许shell脚本按照字面意义解释$,而不是引用变量.
    $ echo "The cost of the item is \$15"
        The cost of the item is $15
可以通过${variable}形式引用的变量。{} 通常用于帮助界定$后的变量名。

4.2,用户自定义变量

用户自定义变量的名称可以是任何由字母、数字或下划线组成的字符串,长度不能超过20个字符。变量名区分大小写.
使用等号为变量赋值。在变量、等号和值之间不能出现空格.
    var1=10
    var2=-57
    var3=testing
    var4="still more testing"
shell脚本会以字符串形式存储所有的变量值,脚本中的各个命令可以自行决定变量值的数据类型。
shell脚本中定义的变量在脚本的整个生命周期里会一直保持着它们的值,在脚本结束时会被删除。

用户自定义变量可以通过$引用
    $ cat test3
        #!/bin/bash
        # testing variables
        days=10
        guest="Katie"
        echo "$guest checked in $days days ago"
        days=5
        guest="Jessica"
        echo "$guest checked in $days days ago"
    $ chmod u+x test3
    $ ./test3
        Katie checked in 10 days ago
        Jessica checked in 5 days ago
重要:引用变量值时要加$,对变量赋值时则不用加$。
    #!/bin/bash
    value1=10
    value2=value1
    echo The resulting value is $value2
    $ ./test4
        The resulting value is value1
    $ cat test4
        #!/bin/bash
        value1=10
        value2=$value1
        echo The resulting value is $value2
    $ ./test4
        The resulting value is 10

4.3,命令替换 $() ``

可以从命令输出中提取信息并将其赋给变量 !!!

将命令输出赋给变量有两种方法:
    ·反引号(`)
    ·$()格式

命令替换允许将shell命令的输出赋给变量,赋值号和命令替换符之间没有空格。
    testing=`date`
    testing=$(date)
    
在脚本中通过命令替换获得当前日期并用其来生成唯一文件名:
    #!/bin/bash
    today=$(date +%y%m%d)
    ls /usr/bin -al > log.$today

命令替换会创建出 子shell 来运行指定命令,这是由运行脚本的shell所生成的一个独立的shell。因此,在子shell中运行的命令无法使用脚本中的变量 !!!。
如果在命令行中使用./路径执行命令,就会创建子shell.如果不加路径,则不会创建子shell。
不过,内建的 shell命令也不会创建子shell。

5,重定向输入和输出

想要保存命令的输出 而不只是在屏幕上显示。
bash shell提供了几个运算符,可以将命令的输出重定向到其他位置(比如文件)
重定向既可用于输入,也可用于输出,例如将文件重定向,作为命令输入

5.1,输出重定向

最基本的重定向会将命令的输出发送至文件。 bash shell使用大于号(>)来实现该操作:
    command > outputfile
命令输出会被保存到指定的输出文件中:
    $ date > test6
    $ ls -l test6
        -rw-r--r--    1 user     user           29 Jun 01 16:56 test6
    $ cat test6
        Mon Jun 01 16:56:58 EDT 2020
重定向 运算符创建了文件test6(使用默认的umask设置)并将 date命令的输出重定向至该文件。
如果输出文件已存在,则重定向运算符会用新数据覆盖已有的文件.

命令输出追加到已有文件中用双大于号(>>)来追加数据:
    $ date >> test6

5.2,输入重定向

输入重定向和输出重定向正好相反。
输入重定向会将文件的内容重定向至命令,而不是将命令输出重定向至文件

输入重定向运算符是小于号(<):
    command < inputfile
重定向
    $ wc < test6
          2      11      60
wc命令可以统计数据中的文本。在默认情况下,会输出3个值。: 文本的行数;文本的单词数;文本的字节数

另外一种输入重定向的方法,称为内联输入重定向(inline input redirection)
无须使用文件进行重定向,只需在命令行中指定用于输入重定向的数据即可。

内联输入重定向运算符是(<<)。除了这个符号,必须指定一个文本标记来划分输入数据的起止。任何字符串都可以作为文本标记,但在数据开始和结尾的文本标记必须一致:
    格式:
        command << marker
        data
        marker
    使用(EOF PS2环境变量中定义的次提示符)
        $ wc << EOF
        > test string 1
        > test string 2
        > test string 3 
        > EOF
             3       9      42

6,管道 |

将一个命令的输出作为另一个命令的输入。通过重定向来实现有些笨拙:
        $ rpm -qa > rpm.list
        $ sort < rpm.list
        abattis-cantarell-fonts-0.0.25-1.el7.noarch
        ... ...
    rpm命令通过Red Hat软件包管理系统(RPM)管理系统(比如上例中的CentOS系统)中已安装的软件包。配合-qa选项使用时,会生成已安装包的列表。

无须将命令输出重定向至文件,可以将其直接传给另一个命令。这个过程称为管道连接(piping).

管道 符号由两个竖线构成,一个在上,一个在下。然而,其印刷体往往看起来更像是单个竖线(|)。
管道被置于命令之间,将一个命令的输出传入另一个命令中:
    command1 | command2
当第一个命令产生输出时,它会被立即传给第二个命令。数据传输不会用到任何中间文件或缓冲区。
管道可以串联的命令数量没有限制。可以持续地将命令输出通过管道传给其他命令来细化操作。
    $ rpm -qa | sort
    $ rpm -qa | sort | more
    $ rpm -qa | sort > rpm.list

7,执行数学运算 expr;[];

7.1,expr命令

在命令行中执行数学运算(笨拙,了解,不用)
    $ expr 1 + 5
        6
能够识别少量算术运算符和字符串运算符     
运算符描述
ARG1ARG2
ARG1 & ARG2如果ARG1和ARG2都不为null或0,就返回ARG1;否则,返回0
ARG1 < ARG2如果ARG1小于ARG2,就返回1;否则,返回0
ARG1 <= ARG2如果ARG1小于或等于ARG2,就返回1;否则,返回0
ARG1 = ARG2如果ARG1等于ARG2,就返回1;否则,返回0
ARG1 != ARG2如果ARG1不等于ARG2,就返回1;否则,返回0
ARG1 >= ARG2如果ARG1大于或等于ARG2,就返回1;否则,返回0
ARG1 > ARG2如果ARG1大于ARG2,就返回1;否则,返回0
ARG1 + ARG2返回ARG1和ARG2之和
ARG1 - ARG2返回ARG1和ARG2之差
ARG1 * ARG2返回ARG1和ARG2之积
ARG1 / ARG2返回ARG1和ARG2之商
ARG1 % ARG2返回ARG1和ARG2之余数
STRING:REGEXP如果REGEXP模式匹配STRING,就返回该模式匹配的内容
match STRING REGEXP如果REGEXP模式匹配STRING,就返回该模式匹配的内容
substr STRING POS LENGTH返回起始位置为POS(从1开始计数)、长度为LENGTH的子串
index STRING CHARS返回CHARS在字符串STRING中所处的位置;否则,返回0
length STRING返回字符串STRING的长度
  • TOKEN |将TOKEN解释成字符串,即使TOKEN属于关键字
    (EXPRESSION) |返回EXPRESSION的值

    容易被shell错误解释的字符被传入expr命令之前,使用shell的转义字符(反斜线)对其进行转义:
    $ expr 5 * 2
    10
    要将一个数学算式的结果赋给变量,需要使用命令替换来获取expr命令
    sh中使用
    #!/bin/bash
    var1=10
    var2=20
    var3=$(expr $var2 / $var1)
    echo The result is $var3

7.2,方括号[]

为了兼容 Bourne shell,bash shell保留了expr命令,同时也提供了另一种更简单的方法来执行数学运算。
在bash中,要将数学运算结果赋给变量,可以使用 $和方括号($[ operation ])
    $ var1=$[1 + 5]
    $ echo $var1
        6
    $ var2=$[$var1 * 2]
    $ echo $var2
        12
用方括号来执行数学运算要比expr命令方便
    #!/bin/bash
    var1=100
    var2=50
    var3=45
    var4=$[$var1 * ($var2 - $var3)]
    echo The final result is $var4
使用方括号执行数学运算时,无须担心shell会误解乘号或其他符号,不需要转义.

仍然存在局限性,bash shell的数学运算符只支持整数运算。
    $ cat test8
    #!/bin/bash
    var1=100
    var2=45
    var3=$[$var1 / $var2]
    echo The final result is $var3
    $ chmod u+x test8
    $ ./test8
    The final result is 2
! z shell(zsh)提供了完整的浮点数操作。

7.3,浮点数解决方案

最常见的做法是使用内建的bash计算器 bc
7.3.1,bash计算器 bc的基本用法
bash计算器实际上是一种编程语言,允许在命令行中输入浮点数表达式,然后解释并计算该表达式,最后返回结果
bash计算器能够识别
    ·数字(整数和浮点数)
    ·变量(简单变量和数组)
    ·注释(以#或C语言中的/* */开始的行)
    ·表达式
    ·编程语句(比如if-then语句)
    ·函数
通过bc命令访问 bash计算器:
    $ bc
    bc 1.06.95
    Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
    This is free software with ABSOLUTELY NO WARRANTY.
    For details type 'warranty'.
    12 * 5.4    ##计算
    64.8        ##结果
    3.156 * (3 + 5)  ##计算
    25.248   ##结果
    quit    ##退出

浮点数运算是由 内建变量 scale 控制。必须将该变量的值设置为希望在计算结果中保留的小数位数,(scale变量的默认值是0)
    $ bc -q
    3.44 / 5
        0
    scale=4
    3.44 / 5
        .6880
    quit
    $
-q选项 不显示 bash计算器 的 欢迎信息。
7.3.2,在脚本中使用bc
用命令替换来运行bc命令,将输出赋给变量。
    variable=$(echo "options; expression" | bc)
options 设置变量。需要多个变量,可以用分号来分隔。
expression 定义要通过bc执行的数学表达式。
    $ cat test9
        #!/bin/bash
        var1=$(echo " scale=4; 3.44 / 5" | bc)
        echo The answer is $var1
    $ chmod u+x test9
    $ ./test9
        The answer is .6880
    $ cat test11
        #!/bin/bash
        var1=20
        var2=3.14159
        var3=$(echo "scale=4; $var1 * $var1" | bc)
        var4=$(echo "scale=4; $var3 * $var2" | bc)
        echo The final result is $var4

进行大量运算,使用输入重定向.
bc命令能接受输入重定向,允许将一个文件重定向到bc命令来处理。避免将表达式输入到文件中可以使用内敛输入重定向.
使用内联输入重定向,允许直接在命令行中重定向数据。在shell脚本中,可以将输出赋给一个变量:
    variable=$(bc << EOF
    options
    statements
    expressions
    EOF
    )
示例: 可以在bash计算器中为变量赋值,仅在计算器中有效
    $ cat test12
    #!/bin/bash
    var1=10.46
    var2=43.67
    var3=33.2
    var4=71
    var5=$(bc << EOF
    scale = 4
    a1 = ( $var1 * $var2)
    b1 = ($var3 * $var4)
    a1 + b1
    EOF
    )
    echo The final answer for this mess is $var5

8,退出脚本 exit 0~255

执行完最后一条命令,脚本就结束了。
shell中运行的每个命令都使用退出状态码来告诉 shell自身已经运行完毕。退出状态码是一个0~255的整数值,在命令结束运行时由其传给shell。
可以获取这个值并在脚本中使用。

8.1,查看退出状态码

Linux提供了 专门的变量 $? 来保存最后一个已执行命令的退出状态码。
对于需要进行检查的命令,必须在其运行完毕后立刻查看或使用$?变量
    $ date
        Mon Jun 01 16:01:30 EDT 2020
    $ echo $?
        0
按照惯例,对于成功结束的命令,其退出状态码是0。对于因错误而结束的命令,其退出状态码是一个正整数:
    $ asdfg
        -bash: asdfg: command not found
    $ echo $?
        127
code描述
0命令成功结束
1一般性未知错误
2不适合的shell命令
126命令无法执行
127没找到命令
128无效的退出参数
128+x与Linux信号x相关的严重错误
130通过Ctrl+C终止的命令
255正常范围之外的退出状态码

8.2 exit命令

shell脚本会以脚本中的最后一个命令的退出状态码退出
    $ ./test6
    The result is 2
    $ echo $?
        0
exit命令允许在脚本结束时指定一个退出状态码,可以使用变量作为exit命令的参数(退出状态码最大只能是255,超出会进行模256运算)
    $ cat test13
        #!/bin/bash
        # testing the exit status
        var1=10
        var2=30
        var3=$[ $var1 + $var2 ]
        echo The answer is $var3
        exit 5
    $ chmod u+x test13
    $ ./test13
        The answer is 40
    $ echo $?
        5

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值