shell 编程(二):语法结构 - 基础
shell 语法结构(基础部分)
一、变量
shell 作为一种编程语言来说肯定是会有变量的定义的,但是却不同于一般的编程语言,shell对于变量的定义具有严格的格式限制。
- 所有的变量名必须为大写
- 变量名中只可以出现下划线
- 变量定义分为环境变量和本地变量
- 变量定义时等号左右没有空格(有空格会被当作命令和参数执行)
1.环境变量
环境变量是可以由父进程传递给子进程的,因此 shell 进程中的环境变量可以从当前 shell 进程传给 fork 出来的子进程。
使用下面的命令可以显示当前 shell 进程中所有的环境变量:
$ printenv
2.本地变量
本地变量只能存在于当前 shell 进程中。
使用下面的命令可以显示当前 shell 进程中所定义的所有变量(包括本地变量和环境变量)和函数:
$ set
环境变量是任何进程都有的概念,而本地变量是 shell 特有的概念。
3.定义变量
在 shell 中,环境变量和本地变量的定义和用法基本一致。
在 shell 中定义或赋值一个本地变量:
$ VARNAME=value
该变量被定义好之后只是一个普通的本地变量,可以使用如下的命令将本地变量导出为环境变量:
$ export VARNAME
通常定义和导出环境变量可以一步完成:
$ export VARNAME=value
4.删除变量
使用如下的命令来删除一个本地变量或者环境变量:
$ unset VARNAME
5.获取变量的值
在 shell 中获取一个变量的时候不能直接用变量名,而是使用用 ${VARNAME}来表示它的值,也可以简写为 $VARNAME :
echo $VARNAME
注意:
- 在定义变量时不用 $ ,取变量值时要用 $ 。
- 和 C 语言不同的是,shell 变量不需要明确定义类型。(事实上 shell 变量的值都是字符串,比如我们定义VAR=45,其实VAR的值是字符串45而非整数)
- shell 变量不需要先定义后使用,如果对一个没有定义的变量取值,则值为空字符串。
二、文件名代换(Globbing)
在 shell 脚本中也是可以使用一些 通配符(Wildcard) 来匹配字符串的,shell 所支持的通配符如下:
- *:匹配0个或多个任意字符
- ?:匹配一个任意字符
- [若干字符]:匹配方括号中任意一个字符的一次出现
其实这些通配符也就是正则表达式,可以实现对某一类字符串进行匹配。
$ ls /dev/ttyS*
$ ls ch0?.doc
$ ls ch0[0-2].doc
$ ls ch[012] [0-9].doc
注意,Globbing 所匹配的文件名是由 shell 展开的,也就是说在参数还没传给程序之前已经展开了,比如上述 ls ch0[012].doc 命令,如果当前目录下有 ch00.doc 和 ch02.doc,则传给 ls 命令的参数实际上是这两个文件名,而不是一个匹配字符串。
三、命令代换
如何在定义变量的时候将一个某个命令的执行结果赋值给该命令呢?
其实,由 ` 反引号括起来的是一条命令,shell 先执行该命令,然后将输出结果立刻代换到当前命令行中。
例如定义一个变量存放 date 命令的输出:
$ DATE=`date`
$ echo $DATE
命令代换也可以用 $() 表示:
$ DATE=$(date)
四、算术代换
1.加减乘除运算
算术运算法 $(()) 用于进行算术计算,$(()) 中的 shell 变量取值将转换成整数,同样含义的 $[] 等价例如:
$ VAR=45
$ echo $(($VAR+3))
$(()) 中只能用 +-*/ 和 () 运算符,并且只能做整数运算。
2.进制表示
$[base#n],其中base表示进制,n 按照 base 进制解释,后面再有运算数,按十进制解释。
echo $[2#10+11]
echo $[8#10+11]
echo $[10#10+11]
五、转义字符
和 C 语言类似,\ 在 shell 中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义(回车除外),换句话说,紧跟其后的字符取字面值。例如:
$ echo $SHELL
# /bin/bash
$ echo \$SHELL
# $SHELL
$ echo \\
\
比如创建一个文件名为“$ $”的文件可以这样:
$ touch \$\ \$
还有一个字符虽然不具有特殊含义,但是要用它做文件名也很麻烦,就是 - 号。如果要创建一个文件名以-号开头的文件,这样是不行的:
$ touch -hello
# touch: invalid option -- h
# Try `touch --help' for more information.
# 即使加上\转义也还是报错:
$ touch \-hello
# touch: invalid option -- h
# Try `touch --help' for more information.
这是因为各种 UNIX 命令都把 - 号开头的命令行参数当作命令的选项,而不会当作文件名。如果非要处理以-号开头的文件名,可以有两种办法:
$ touch ./-hello
或者
$ touch -- -hello
\ 符号其实还有一种用法,在\后敲回车表示续行,Shell并不会立刻执行命令,而是把光标移到下一行,给出一个续行提示符>,等待用户继续输入,最后把所有的续行接到一起当作一个命令执行。例如:
itcast$ ls \
> -l
# (ls -l命令的输出)
六、引号
1.单引号
和 C 语言不一样,shell 脚本中的单引号和双引号一样都是字符串的界定符,而不是字符的界定符。
单引号用于保持引号内所有字符的字面值,即使引号内的\和回车也不例外,但是字符串中不能出现单引号。如果引号没有配对就输入回车,shell 会给出续行提示符,要求用户把引号配上对。例如:
$ echo '$SHELL'
# $SHELL
$ echo 'ABC\(回车)
> DE'
# (再按一次回车结束命令)
# ABC\
# DE
2.双引号
被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引号的处理方式不同
$ DATE=$(date)
$ echo "$DATE"
# $DATE
$ echo '$DATE'
# Sun Mar 31 12:37:40 UTC 2019
注意:单引号和双引号一定得分清楚,双引号中引的命令的话是会被展开的,而单引号则直接表示为字面值