零基础小白快速了解掌握Shell脚本编程

编程语言分类

静态和动态语言:

  • 静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如Java语言、C语言

  • 动态编译语言:不事先声明,可随时改变类型,如Shell语言、python语言、javascript语言、php语言

强类型和弱类型语言:

  • 强类型语言:不同类型数据操作,必须经过强制转换成同一类型才能运算,如java,C#

  • 弱类型语言:语言的运行时会隐式地做数据类型转换。无需指定类型,默认均为字符型;参与计算会自动进行隐式类型转换;变量无需事先定义可直接调用。如Shell语言,php,JavaScript

脚本检查工具:

yum install -y epel-release

yum install -y ShellCheck

一、Shell脚本语言的基本结构

1.1 Shell脚本的用途:
  • 自动化常用命令

  • 执行系统管理和故障排除

  • 创建简单的应用程序

  • 处理文本或文件

1.2 Shell脚本基本结构:

Shell脚本编程:是基于过程式,解释执行的语言

编程语言的基本结构:

  • 各种系统命令的组合

  • 数据存储:变量,数组

  • 表达式:a+b

  • 控制语句:if、case、for、while

shell脚本:包含一些命令或声明,并符合一定格式的文本文件

格式要求:首行执行声明机制

#声明后续语句是通过那种语言写的
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
1.3 创建Shell脚本过程
  • 使用vim创建文本文件,第一行必须包括shell声明序列:

#!/bin/bash
  • 加执行权限,给予执行权限,在命令行上指定脚本的绝对或相对路径

[root@localhost ~]# chmod +x shellScript/hello.sh 
  • 运行脚本,直接运行解释器,将脚本作为解释器程序的参数运行。

[root@localhost ~]# /root/shellScript/hello.sh 
  • 1.4 脚本注释规范
  1. 第一行一般为调用使用的语言

  2. 程序名,避免更改文件名为无法找到正确的文件

  3. 版本号

  4. 更改后的时间

  5. 作者相关信息

  6. 该程序的作用,及注意事项

  7. 最后是各版本的更新简要说明

1.5 第一个脚本

[root@localhost ~]# cat shell/hostname.sh 
#!/bin/bash
echo "My hostname is `hostname`"
echo "Time is `date +'%F %T'`"
[root@localhost ~]# chmod +x shell/hostname.sh
[root@localhost ~]# shell/hostname.sh
1.6 执行脚本

1、增加执行权限,执行脚本时会创建一个子shell,不影响现有的shell环境

chmod +x 2.sh
./2.sh
/root/shellScript/2.sh

2、使用 . 或者source,执行脚本时不会创建一个子shell,会影响现有的shell环境

source 2.sh
. 2.sh

注意:尽量不要使用该方式执行脚本!!!

实列:备份脚本

[root@localhost ~]# mkdir /backup/
[root@localhost ~]# vim shell/backup.sh
[root@localhost ~]# cat shell/backup.sh 
#!/bin/bash
echo -e "\033[1;32m\033[0m"
sleep 2
cp -av /etc/ /backup/etc`date +%F`/
echo -e "\033[1;32mBackup is finished\033[0m"
[root@localhost ~]# chmod +x shell/backup.sh 
[root@localhost ~]# ./shell/backup.sh 
Starting backup..
...
Backup is finished
1.7 脚本错误
  • 语法错误,会导致后续的命令不继续执行,可以用bash -n shellname检查错误

  • 命令错误,后续的命令还会继续,可以使用bash -x shellname检查

  • 逻辑错误,只能使用bash -x进行观察

1.8 Shell字符串详解

字符串(String)就是一系列字符的组合。字符串是Shell编程中最常用的数据类型之一

字符串可以由单引号''包围,也可以由""包围,也可以不用引号,三种方式的区别

  1. 由单引号' '包围的字符串

    • 任何字符都会原样输出,在其中使用变量是无效的

    • 字符串中不能出现单引号,即使对单引号进行转义也不行

  2. 由双引号" "包围的字符串

    • 如果其中包含了某个变量,那么该变量就会被解析(得到该变量的值),而不是原样输出

    • 字符串中可以出现双引号,只要进行转义就行

  3. 不被引号包围的字符串

    • 不被引号包围的字符串中出现变量也会被解析,这一点和双引号""包围的字符串一样

    • 字符串中不能出现空格,否则空格后面的字符串会作为其他变量或者命令解析

通过代码演示一下三种形式的区别
#!/bin/bash
n=74
str1=c.biancheng.net$n 
str2="shell \"Script\" $n"
str3='C语言中文网 $n'
echo $str1
echo $str2
echo $str3


# 运行结果
c.biancheng.net74
shell "Script" 74
C语言中文网 $n

str1 中包含了$n,它被解析为变量 n 的引用。$n后边有空格,紧随空格的是 str2;Shell 将 str2 解释为一个新的变量名,而不是作为字符串 str1 的一部分

str2 中包含了引号,但是被转义了(由反斜杠\开头的表示转义字符)。str2 中也包含了$n,它也被解析为变量 n 的引用

str3 中也包含了$n,但是仅仅是作为普通字符,并没有解析为变量 n 的引用

获取字符串长度

在Shell中获取字符串长度很简单,具体方法如下:

${#string_name}
string_name:表示字符串名字
1.9 Shell字符串拼接

在脚本语言中,字符串的拼接(也称为字符串连接或者字符串合并)往往都非常简单,例如:

  • PHP中使用.即可连接两个字符串

  • JavaScript中使用+即可将两个字符串合并为一个

然而,在Shell中你不需要使用任何运算符,将两个字符串并排放在一起就能实现拼接

#!/bin/bash
name="shell"
url="http://c.biancheng.net/shell/"
str1=$name$url #中间不能有空格
str1=$name":"$url
str2="$name $url" #如果被双引号包围,那么中间可以有空格,也可以出现别的字符串
str3="$name:$url" 
str4="${name}Script:${url}Index.html" #在变量后加上字符串,需要给变量名加上大括号
1.10 Shell字符串截取

Shell截取字符串通常有两种方式,从指定位置开始截取和从指定字符(子字符串)开始截取

从指定位置开始截取

这种方式需要两个参数:除了指定起始位置,还需要截取长度,才能最终确定要截取的字符串

既然需要指定起始位置,那么就要涉及到计数方向的问题,到底是从字符串左边开始计数,还是从字符串右边开始计数?答案是:Shell同时支持两种计数方式

1.从字符串左边开始计数

如果想从字符串的左边开始计数,那么截取字符串的具体格式如下:

${string:start:length}

`其中,Sting是要截取的字符串,start是起始位置(从左边开始,从0开始计数),length是要截取的长度(省略的话表示直到字符串的末尾)

例如:

url="c.biancheng.net"
echo ${url:2:9}

>结果为:biancheng

url="c.biancheng.net"
echo ${url:2} #省略length,截取到字符串末尾

>结果为:biancheng.net

2.从右边开始计数

如果想从字符串的右边开始计数,那么截取字符串的具体格式如下:

${string:0-start:length}

`同第 1) 种格式相比,第 2) 种格式仅仅多了0-,这是固定的写法,专门用来表示从字符串右边开始计数。

这里需要强调两点:
从左边开始计数时,起始数字是 0(这符合程序员思维);
从右边开始计数时,起始数字是 1(这符合常人思维)
计数方向不同,起始数字也不同。
不管从哪边开始计数,截取方向都是从左到右。

例如:

url="c.biancheng.net"
echo ${url:0-13:9}

>结果为:biancheng 从右边数:b是第13个字符

url="c.biancheng.net"
echo ${url:0-13} #省略length,直接截取到字符串末尾
>结果为:biancheng.net

从指定字符(子字符串)开始截取

这种截取方式无法指定字符串长度,只能从指定字符(子字符串)截取到字符串末尾。Shell可以截取指定字符(子字符串)右边的所有字符,也可以截取左边的所有字符

1)使用#号截取右边字符

使用#号可以截取指定字符(或子字符串)右边的所有字符,具体格式如下:

${string#*chars}

#其中,string 表示要截取的字符,chars 是指定的字符(或者子字符串),*是通配符的一种,表示任意长度的字符串。*chars连起来使用的意思是:忽略左边的所有字符,直到遇见 chars(chars 不会被截取)

例如:

url="http://c.biancheng.net/index.html"
echo ${url#*:}

>结果为://c.biancheng.net/index.html

echo ${url#*p:}
echo ${url#*ttp:}

`如果不需要忽略chars左边的字符,那么也可以不写*
url="http://c.biancheng.net/index.html"
echo ${url#http://}
>结果为:c.biancheng.net/index.html

`注意:以上写法遇到第一个匹配的字符(子字符串)就结束了
url="http://c.biancheng.net/index.html"
echo ${url#*/}
>结果为:/c.biancheng.net/index.html。url 字符串中有三个/,输出结果表明,Shell 遇到第一个/就匹配结束了

使用##可以直到最后一个指定字符(子字符串)再匹配结束

${string##*chars}

例如:

#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url#*/}
# 结果为:/c.biancheng.net/index.html
echo ${url##*/}
# 结果为:index.html

str="-----aa+++aa@@@"
echo ${str#*aa}
# 结果为:+++aa@@@
echo ${str##*aa}
# 结果为:@@@

2)使用%截取左边字符

使用%号可以截取指定字符(或者子字符串)左边的所有字符

${string%chars*}
`请注意*的位置,因为要截取 chars 左边的字符,而忽略 chars 右边的字符,所以*应该位于 chars 的右侧。其他方面%和#的用法相同

#!/bin/bash
url="http://c.biancheng.net/index.html"
echo ${url%/*}  #结果为 http://c.biancheng.net
echo ${url%%/*}  #结果为 http:
str="---aa+++aa@@@"
echo ${str%aa*}  #结果为 ---aa+++
echo ${str%%aa*}  #结果为 ---

汇  总

格式说明
${string:start :length}从string字符串的左边第start个字符开始,向右截取length个字符。
${string:start}从string字符串的左边第start个字符开始截取,直到最后。
${string:0-start:length}从string字符串的右边第start个字符开始,向右截取length个字符。
${string:0-start}从string字符串的右边第start个字符开始截取,直到最后。
${string#*chars}从string字符串第一次出现chars的位置开始,截取chars右边的所有字符。
${string##*chars}从string字符串最后一次出现chars的位置开始,截取chars右边的所有字符。
${string%chars*}从string字符串第一次出现chars的位置开始,截取chars左边的所有字符。
${string%%chars*}从string字符串最后一次出现chars的位置开始,截取chars左边的所有字符。

二、Shell脚本语言的变量用法详解

2.1 变量

变量表示命名的内存空间,将数据放在内存空间中,通过变量名引用,获取数据

2.2 变量类型

变量类型:

  • 内置变量:如PS1,PATH,UID,HOSTNAME,HISTSIZE

  • 用户自定义变量

  • 预定义变量

  • 位置变量

不同的变量存放的数据不同,决定了以下:

  1. 数据存储方式

  2. 参与的计算

  3. 表示的数据范围

变量数据类型:

  • 字符串

  • 数值:整型,浮点型(小数)、bash不支持浮点数

2.3 Shell中变量命名法则
  • 不能使用程序中的保留字,如:if,for

  • 只能使用数字,字母及下划线,且不能以数字开头

  • 见名思意,用英文名字,并体现真正含义

  • 统一命名规则:驼峰命名法

  • 变量名大写

  • 局部变量小写

  • 函数名小写

2.4 变量定义和引用

变量的生效范围(变量作用域)

  • 普通变量:生效范围为当前shell进程;对当前shell之外的其他shell进程,包括当前shell的子shell进程均无效

  • 环境变量:生效范围为当前shell进程及其子进程

  • 本地变量:生效范围为当前shell进程中某代码片段,通常指函数

变量赋值:

name="value"

value可以是以下多种类型
直接字符串:name='root'
变量引用:name="$USER"
命令应用:name=`command`  || name=$(command)
通配符:FILE=/etc/* /*表示etc目录下所有的文件名*/

注意:变量赋值是临时生效,当退出终端后,变量会自动删除,无法持久保存。

变量引用:

$name
${name}

弱引用和强引用:

  • “$name”:弱引用,其中的变量引用会被替换成为变量值

  • ‘$name’:强引用,其中的变量引用不会被替换成变量值,而保持原字符串

实 例:

[root@localhost ~]# name='Mike'
[root@localhost ~]# NAME="$USER"
[root@localhost ~]# hostname=`hostname`
[root@localhost ~]# echo "My name is $name"
My name is Mike
[root@localhost ~]# echo "My name is $NAME"
My name is root
[root@localhost ~]# echo "My hostname is $hostname"
My hostname is localhost.localdomain
[root@localhost ~]# 

[root@localhost ~]# NUM=`seq 10`
[root@localhost ~]# echo $NUM
1 2 3 4 5 6 7 8 9 10
[root@localhost ~]# echo "$NUM"
1
2
3
4
5
6
7
8
9
10
[root@localhost ~]#

查看已定义的所有变量:

[root@localhost ~]#set

删除变量:

[root@localhost ~]#unset shellname1 shellname2
//实例:
[root@localhost ~]# echo $name 
Mike
[root@localhost ~]# unset name
[root@localhost ~]# echo $name 

[root@localhost ~]# 

实例:"{}"的使用

[root@localhost ~]# NAME=mage
[root@localhost ~]# AGE=20
[root@localhost ~]# echo $NAME
mage
[root@localhost ~]# echo $AGE
20
[root@localhost ~]# echo $NAME $AGE
mage 20
[root@localhost ~]# echo $NAME_$AGE
20
[root@localhost ~]# echo ${NAME}_$AGE
mage_20
[root@localhost ~]# 

显示系统信息

[root@localhost ~]# vim shell/OS.sh  
#!/bin/bash
RED="\E[1;31m"
GREEB="\E[1;32m"
END="\E[0m"
echo -e "\E[1;32m----------Host systeminfo----------$END"
echo -e "HOSTNAME: $RED `hostname`$END"
echo -e "IPADDR:   $RED `ifconfig ens160 | grep -Eo '([0-9]{1,3}\.){3}[0-9]{1,3}' | head -n1` $END"
echo -e "OSVERSION: $RED `cat /etc/redhat-release`$END"
echo -e "KERNEL:   $RED `uname -r`$END"
echo -e "CPU:       $RED `lscpu | grep "型号名称:" | tr -s ' ' ' '|cut -d ' ' -f 2-5` $END"
echo -e "MEMORY:   $RED `free -h | grep Mem | tr -s ' ' ' '|cut -d ' ' -f 4` $END"
echo -e "DISK:     $RED `lsblk | grep '^sda' | tr -s ' ' | cut -d ' ' -f 4` $END"
echo -e "\E[1;32m----------       END     ----------$END"
[root@localhost ~]# chmod +x shell/OS.sh 
[root@localhost shellScript]# ./os.sh 
----------Host systeminfo----------
HOSTNAME:  localhost.localdomain
IPADDR:    192.168.115.213 
OSVERSION:  CentOS Linux release 7.9.2009 (Core)
KERNEL:    3.10.0-1160.el7.x86_64
CPU:        11th Gen Intel(R) Core(TM) 
MEMORY:    1.0G 
DISK:      200G 
----------       END     ----------

利用变量实现动态命令

[root@localhost ~]# CMD=hostname
[root@localhost ~]# $CMD
localhost.localdomain
[root@localhost ~]# 
2.5 环境变量

环境变量:

  • 可以使子进程(包括孙子进程)继承父进程的变量,但是无法让父进程使用子进程的变量。

  • 一旦子进程修改了从父进程继承的变量,将会传递新的值给孙子进程

  • 一般只在配置文件中使用,在脚本中较少使用

课程引入:普通变量生效的范围与环境变量生效的范围

[root@localhost ~]# vim shell/father.sh 
#!/bin/bash
NAME=father
echo "father.sh:NAME=$NAME"
echo "fatther is PID=$BASHPID"
shell/son.sh

[root@localhost ~]#vim shell/son.sh
#!/bin/bash
echo "son.sh:NAME=$NAME"
NAME=son
echo "son.sh:NAME=$NAME"
echo "son.sh PID is $BASHPID"
echo "son.sh father pid is $PPID"
sleep 100

[root@localhost ~]#chmod -R +x shell/*

[root@localhost ~]# ./shell/father.sh 
father.sh:NAME=father
fatther is PID=12053
son.sh:NAME=
son.sh:NAME=son
son.sh PID is 12054
son.sh father pid is 12053

#子进程无法使用父进程的变量,需要自己赋值

变量声明和赋值:

export name=VALUE
declare -x name =VALUE

#或者先赋值再声明~

value可以是以下多种类型
直接字符串:name='root'
变量引用:name="$USER"
命令应用:name=`command`  || name=$(command)
通配符:FILE=/etc/* /*表示etc目录下所有的文件名*/

declare命令详解:(了解)

declare 为 shell 指令,在第一种语法中可用来声明变量并设置变量的属性([rix]即为变量的属性),在第二种语法中可用来显示 shell 函数。若不加上任何参数,则会显示全部的 shell 变量与函数(与执行 set 指令的效果相同)

语法

declare [+/-][rxi][变量名称=设置值] 或 declare -f

参数说明

  • +/-  "-“可用来指定变量的属性,”+"则是取消变量所设的属性。

  • -f   仅显示函数

  • r   将变量声明为只读变量。注意,一旦设置为只读变量,既不能修改变量的值也不能删除变量,甚至不能通过+r取消只 读属性

  • x   指定的变量会成为环境变量,可供shell以外的程序来使用

  • i   将变量声明为整数型(integer)

  • p 显示指定变量的被声明类型。

实例

1.声明整数型变量

#!/bin/bash
declare -i ab //声明整数型变量
ab=56 //改变变量内容
echo $ab //显示变量内容

--->
56

2.改变变量属性

#!/bin/bash
#声明整数型变量
declare -i ef 
ef=1
echo $ef
#变量赋值,赋予文本值
ef="wer"
echo $ef
#取消变量属性
declare +i ef
ef="wer"
echo $ef

3.设置变量只读

#!/bin/bash
declare -r ab #设置变量为只读
ab=88 #改变变量内容
echo $ab #显示变量内容

--->
declare.sh:行3: ab: 只读变量

4.声明数组变量

#!/bin/bash
#声明数组变量
declare -a cd
cd[0]=a
cd[1]=b
cd[2]=c
#输出数组的指定内容
echo ${cd[1]}
#显示整个数组变量内容
echo ${cd[@]}

5.显示函数

#!/bin/bash
#声明函数
declare -f 
function command_not_found_handle(){
    if [ -x /usr/lib/command_not_found_handle ];then
        /usr/bin/python /usr/lib/command_not_found_handle -- $1;
        return $?;
    else
        if [ -x /usr/share/command_not_found_handle ];then
        /usr/bin/python /usr/share/command_not_found_handle --$1;
        return $?;
        else
        return 127;
        fi;
    fi;
}

变量引用:

$name
${name}

完善课程导入:

[root@localhost ~]# vim shell/father.sh 
#!/bin/bash
NAME=father
export NAME
echo "father.sh:NAME=$NAME"
echo "fatther is PID=$BASHPID"
shell/son.sh

[root@localhost ~]#vim shell/son.sh
#!/bin/bash
echo "son.sh:NAME=$NAME"
NAME=son
echo "son.sh:NAME=$NAME"
echo "son.sh PID is $BASHPID"
echo "son.sh father pid is $PPID"
sleep 100

[root@localhost ~]#chmod -R +x shell/*

[root@localhost ~]# ./shell/father.sh 
father.sh:NAME=father
fatther is PID=12053
son.sh:NAME=father
son.sh:NAME=son
son.sh PID is 12054
son.sh father pid is 12053
[root@localhost ~]# ./shell/father.sh 
father.sh:NAME=father
fatther is PID=12142
son.sh:NAME=father
son.sh:NAME=son
son.sh PID is 12143
son.sh father pid is 12142
 
 #父进程定义了一个环境变量,在子进程上可以进行调用
 #父进程无法使用子进程的变量
 #子进程自己定义了一个同名变量,就覆盖环境变量

显示所有环境变量:

[root@localhost ~]# env
[root@localhost ~]# printenv
[root@localhost ~]# export
[root@localhost ~]# declare -x

删除变量

[root@localhost ~]#unset shellname1 shellname2

Bash内建的环境变量

PATH
SHELL
USER
UID
PWD
SHLVL #shell的嵌套层数,即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_      #下划线,表示前一命令的最后一个参数

6、只读变量

只读变量:只能声明定义,但后续不能修改和删除

声明只读变量:

readonly name
declare -r name

查看只读变量:

readonly [-p]
declare -r

7、位置与预定义变量

位置变量:在Bash Shell中内置的变量,在脚本代码中调用命令行传递给脚本的参数

位置变量:是指通过命令行传输脚本参数
$1,$2,... 对应第一个,第二个等参数,shift[n]换位置,最多9个
#预定义变量
$0  命令本身,包括路径
$*  传递给脚本的所有参数,全部参数合成一个字符串
$@  传递给脚本的所有参数,每个参数为独立字符串
$#  传递给脚本的参数的个数
$?	上个命令的退出状态,或函数的返回值
$$	当前shell进程ID。对于Shell脚本,就是这些脚本所在的进程ID

注意:$@,$*只有被双引号括起来的时候才会有差异

清空所有位置变量:

set --
//写在脚本内部

实例演示1:

[root@localhost ~]# vim shell/ARG.sh
#!/bin/bash
echo "1st arg is $1"
echo "2st arg is $2"
echo "3st arg is $3"
echo "4st arg is $4"
echo "The number of are is $#"
echo "All args are $*"
echo "All args are $@"
echo "The scriptname is `basename $0`"
[root@localhost ~]# chmod +x shell/ARG.sh 
[root@localhost ~]# shell/ARG.sh {1..10}
1st arg is 1
2st arg is 2
3st arg is 3
4st arg is 4
The number of are is 10
All args are 1 2 3 4 5 6 7 8 9 10
All args are 1 2 3 4 5 6 7 8 9 10
The scriptname is ARG.sh
[root@localhost ~]# 

实例演示2:编写一个移动文件脚本

[root@localhost ~]# vim shell/move.sh
#!/bin/bash
WANGING_COLOR="echo -e \E[1;31m"
END="\E[0m"
DIR=/tmp/`date +%F_%H-%M-%S`
mkdir $DIR
mv $*  $DIR
${WANGING_COLOR} MOVE $* to $DIR $END
[root@localhost ~]# chmod +x shell/move.sh
[root@localhost ~]# touch {a,b,c}
[root@localhost ~]# ls
a  anaconda-ks.cfg  b  c  shell
[root@localhost ~]# shell/move.sh a b c
 MOVE a b c to /tmp/2022-08-16_10-07-55 
[root@localhost ~]# tree /tmp/
/tmp/
└── 2022-08-16_10-07-55
    ├── a
    ├── b
    └── c

1 directory, 3 files
[root@localhost ~]# 

8、 退出状态码变量

进程执行后,将使用变量 ? 保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败, ?保存状态码的相关数字,不同的值反应成功与失败,的取值范围为[0,255]

$?的值为0 代表成功
$?的值不为0 代表失败

用户可以在脚本中使用以下命令自定义退出状态码

exit [n]

实例:

[root@localhost ~]# ping -c 2 www.baidu.com > /dev/null 
[root@localhost ~]# echo $?
0
[root@localhost ~]# cmd
-bash: cmd: 未找到命令
[root@localhost ~]# echo $?
127
[root@localhost ~]# 

注意:

  • 脚本中一旦遇到了exit命令,脚本会立即终止;终止退出状态取决于exit命令后面的数字

  • 如果未给脚本指定退出状态码,整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码

实例1:$?获取上一个命令的退出状态

#!/bin/bash
if [ "$1"==100 ];then
	exit 0 #参数正确,退出状态为0
else
	exit 1 #参数错误,退出状态为1
fi

exit表示退出当前 Shell 进程,我们必须在新进程中运行 test.sh,否则当前 Shell 会话(终端窗口)会被关闭,我们就无法取得它的退出状态了

[root@localhost re_study]# bash test.sh 100
[root@localhost re_study]# echo $?
0
[root@localhost re_study]# bash test.sh 99
[root@localhost re_study]# echo $?
1
[root@localhost re_study]# 

实例2:$?获取函数的返回值

#!/bin/bash
#得到两个数相加的和
function add(){
	return `expr $1 + $2`
}
add 23 50 #调用函数
echo $? #获取函数返回值
# 运行结果:
[root@localhost re_study]# bash test.sh
73

9、 展开命令行

9.1展开命令执行顺序

把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明(~)
命令替换$()和``
再次把命令行分成命令词
展开文件通配(*,?,[abc]等)
准备I/O重导向(<,>)
运行命令

9.2 防止扩展

反斜线(\)会使随后的字符按原意解释

实例:

[root@localhost ~]# echo Your cost: \$5.00
Your cost: $5.00
[root@localhost ~]#
9.3 加引号来防止扩展

单引号' '防止所有扩展
双引号" "可防止扩展,但是以下清空例外:$(美元符号)

9.4 变量扩展

``:反引号,命令替换  等效于 $(ls)
作用: 将命令执行的结果复制下来
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换

                                                      期待下一周更新!!!!!

Linux Shell高级技巧实战总结 一、将输入信息转换为大写字符后再进行条件判断 二、为调试信息设置输出级别 三、判断参数是否为数字 四、判断整数变量的奇偶性 五、将Shell命令赋值给指定变量,以保证脚本的移植性 六、获取当前时间距纪元时间(1970年1月1日)所经过的天数 七、非直接引用变量 八、在循环中使用管道的技巧 九、自链接脚本 十、Here文档的使用技巧 十一、获取进程的运行时长(单位: 分钟) 十二、模拟简单的top命令 十三、格式化输出指定用户的当前运行进程 十四、用脚本完成which命令的基本功能 十五、验证输入信息是否合法 十六、整数验证 十七、判断指定的年份是否为闰年 十八、将单列显示转换为多列显示 十九、将文件的输出格式化为指定的宽度 二十、监控指定目录下磁盘使用空间过大的用户 二十一、编写一个更具可读性的df命令输出脚本 二十二、编写一个用于添加新用户的脚本 二十三、kill指定用户或指定终端的用户进程 二十四、判断用户输入(是/否)的便捷方法 二十五、通过FTP下载指定的文件 二十六、文件锁定 二十七、用小文件覆盖整个磁盘 二十八、统计当前系统中不同运行状态的进程数量 二十九、浮点数验证 三十、统计英文文章中每个单词出现的频率 Linux Shell经典实例解析--Oracle启动脚本(上) Linux Shell经典实例解析--Oracle启动脚本(下)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值