编程语言分类
静态和动态语言:
-
静态编译语言:使用变量前,先声明变量类型,之后类型不能改变,在编译时检查,如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.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编程中最常用的数据类型之一
字符串可以由单引号''
包围,也可以由""
包围,也可以不用引号,三种方式的区别
-
由单引号
' '
包围的字符串-
任何字符都会原样输出,在其中使用变量是无效的
-
字符串中不能出现单引号,即使对单引号进行转义也不行
-
-
由双引号
" "
包围的字符串-
如果其中包含了某个变量,那么该变量就会被解析(得到该变量的值),而不是原样输出
-
字符串中可以出现双引号,只要进行转义就行
-
-
不被引号包围的字符串
-
不被引号包围的字符串中出现变量也会被解析,这一点和双引号
""
包围的字符串一样 -
字符串中不能出现空格,否则空格后面的字符串会作为其他变量或者命令解析
-
通过代码演示一下三种形式的区别
#!/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
-
用户自定义变量
-
预定义变量
-
位置变量
不同的变量存放的数据不同,决定了以下:
-
数据存储方式
-
参与的计算
-
表示的数据范围
变量数据类型:
-
字符串
-
数值:整型,浮点型(小数)、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)
作用: 将命令执行的结果复制下来
\:反斜线,禁止单个字符扩展
!:叹号,历史命令替换
期待下一周更新!!!!!