Bash的基本语法
1.echo命令
echo
命令的作用是在屏幕输出一行文本
|
|
如果想要输出的是多行文本,即包括换行符,需要把多行文本放在引号里
|
|
-n 参数
默认情况,echo
输出的文本末尾会有一个回车符.-n
参数可以取消末尾的回车符,使得下一个提示符紧跟在输出内容的后面.
|
|
-e参数
-e
参数会解释引号内的特殊字符
如不使用-e
参数,即默认情况下,引号会让特殊字符变成普通字符.
|
|
2.命令格式
命令行环境中,主要使用Shell命令,格式为
|
|
command是具体命令或可执行文件,arg为传递给命令的参数 是可选的.
|
|
Bash 单个命令一般都是一行,用户按下回车键,就开始执行。有些命令比较长,写成多行会有利于阅读和编辑,这时可以在每一行的结尾加上反斜杠,Bash 就会将下一行跟当前行放在一起解释。
|
|
3.空格
Bash使用空格(或Tab)区分不同的参数
|
|
如果参数之间有多个空格,Bash会自动忽略多余的空格
|
|
4.分号
分号是命令结束符,使得一行可以放置多个命令,上一个命令执行结束后,再执行第二个命令.
|
|
5.命令的组合符&&
和||
|
|
如果Command1运行成功,则继续运行Command2命令
|
|
Command1运行失败,则继续运行Command2
6.type命令
用来查询一个命令式内部命令还是外部命令
|
|
type
命令的-t
参数,可以返回一个命令的类型:别名(alias),关键词(keyword),函数(function),内置命令(builtin)和文件(file)。
7.快捷键
常用的快捷键
- Ctrl + L:清除屏幕井将当前行移到页面顶部
- Ctrl + C:中止当前正在执行的命令
- Shift + PageUp:向上滚动
- Shift + PageDown:向下滚动
- Ctrl + U:从光标位置删除到首行
- Ctrl + K:从光标位置删除到尾行
- Ctrl + D:关闭Shell会话
↑
,↓
:浏览已执行命令的历史记录
Bash的模式扩展
Shell 接收到用户输入的命令以后,会根据空格将用户的输入,拆分成一个个词元(token)。然后,Shell 会扩展词元里面的特殊字符,扩展完成后才会调用相应的命令。
这种特殊字符的扩展,称为模式扩展(globbing)。其中有些用到通配符,又称为通配符扩展(wildcard expansion)。Bash 一共提供八种扩展。
- 波浪线扩展
?
字符扩展*
字符扩展- 方括号扩展
- 大括号扩展
- 变量扩展
- 子命令扩展
- 算术扩展
2.波浪线扩展
波浪线 ~ 会自动扩展成当前用户的主目录
|
|
~/dir
表示扩展成主目录的某个子目录,dir
是主目录里面的一个子目录名
|
|
3.?
字符扩展
?
字符代表文件路径里面的任意单个字符,不包括空字符。比如,Data???
匹配所有Data
后面跟着三个字符的文件名。
|
|
?
表示单个字符,多个字符需要多个?连用
|
|
4.*
字符扩展
*
字符代表文件路径里面的任意数量的字符,包括零个字符
|
|
5.方括号扩展
方括号扩展的形式是[...]
,只有文件确实存在的前提下才会扩展。如果文件不存在,就会原样输出。括号之中的任意一个字符。比如,[aeiou]
可以匹配五个元音字母中的任意一个。
|
|
方括号扩展还有两种变体:[^...]
和[!...]
。它们表示匹配不在方括号里面的字符,这两种写法是等价的。比如,[^abc]
或[!abc]
表示匹配除了a
、b
、c
以外的字符。
|
|
6.[start-end]扩展
方括号扩展一个简写形式[start-end],表示匹配一个连续的范围。比如,[a-c]
等同于[abc]
,[0-9]
匹配[0123456789]
。
|
|
下面是一些常见简写的例子
[a-z]
:所有小写字母。[a-zA-Z]
:所有小写字母与大写字母。[a-zA-Z0-9]
:所有小写字母、大写字母与数字。[abc]*
:所有以a
、b
、c
字符之一开头的文件名。program.[co]
:文件program.c
与文件program.o
。BACKUP.[0-9][0-9][0-9]
:所有以BACKUP.
开头,后面是三个数字的文件名。
这种简写形式有一个否定形式[!start-end]
,表示匹配不属于这个范围的字符。比如,[!a-zA-Z]
表示匹配非英文字母的字符。
|
|
7.大括号扩展
大括号扩展{...}
表示分别扩展成大括号里面的所有值,各个值之间使用逗号分隔。比如,{1,2,3}
扩展成1 2 3
。
|
|
注意,大括号扩展不是文件名扩展。它会扩展成所有给定的值,而不管是否有对应的文件存在。
|
|
上面例子中,即使不存在对应的文件,{a,b,c}
依然扩展成三个文件名,导致ls
命令报了三个错误。
另一个需要注意的地方是,大括号内部的逗号前后不能有空格。否则,大括号扩展会失效。
|
|
上面例子中,逗号前后有空格,Bash 就会认为这不是大括号扩展,而是三个独立的参数。
逗号前面可以没有值,表示扩展的第一项为空。
|
|
大括号可以嵌套。
大括号也可以与其他模式联用,并且总是先于其他模式进行扩展。
上面例子中,会先进行大括号扩展,然后进行*
扩展。
大括号可以用于多字符的模式,方括号不行(只能匹配单字符)。
|
|
由于大括号扩展{...}
不是文件名扩展,所以它总是会扩展的。这与方括号扩展[...]
完全不同,如果匹配的文件不存在,方括号就不会扩展。这一点要注意区分。
|
|
8.{start..end}扩展
大括号扩展有一个简写形式{start..end}
,表示扩展成一个连续序列。比如,{a..z}
可以扩展成26个小写英文字母。
|
|
如果整数前面有前导0,扩展输出的每一项都有前导0:
|
|
这种简写形式还可以使用第二个双点号(startendstep
),用来指定扩展的步长。
|
|
上面代码将0
扩展到8
,每次递增的长度为2
,所以一共输出5个数字。
多个简写形式连用,会有循环处理的效果
|
|
9 变量扩展
|
|
上面例子中,${!S*}
扩展成所有以S
开头的变量名。
10 子命令扩展
$(...)
可以扩展成另一个命令的运行结果,该命令的所有输出都会作为返回值。
|
|
11.算数扩展
$((...))
可以扩展成整数运算的结果,详见《Bash 的算术运算》一章。
|
|
12.字符串
[[:class:]]
表示一个字符类,扩展成某一类特定字符之中的一个。常用的字符类如下。
[[:alnum:]]
:匹配任意英文字母与数字[[:alpha:]]
:匹配任意英文字母[[:blank:]]
:空格和 Tab 键。[[:cntrl:]]
:ASCII 码 0-31 的不可打印字符。[[:digit:]]
:匹配任意数字 0-9。[[:graph:]]
:A-Z、a-z、0-9 和标点符号。[[:lower:]]
:匹配任意小写字母 a-z。[[:print:]]
:ASCII 码 32-127 的可打印字符。[[:punct:]]
:标点符号(除了 A-Z、a-z、0-9 的可打印字符)。[[:space:]]
:空格、Tab、LF(10)、VT(11)、FF(12)、CR(13)。[[:upper:]]
:匹配任意大写字母 A-Z。[[:xdigit:]]
:16进制字符(A-F、a-f、0-9)。
13.使用注意点
- 通配符是先解释,再执行
- 文件名扩展在不匹配时,会原样输出
- 只适用于单层路径
引号和转义
1.转义
某些字符在Bash里面有特殊含义($ & *)
输出$date
不会有任何结果,因为$
是一个特殊字符。
如果想要原样输出这些特殊字符,就必须在它们前面加上反斜杠,使其变成普通字符。这就叫做“转义”(escape)。
|
|
反斜杠本身也是特殊字符,如果想要原样输出反斜杠,就需要对它自身转义.
\a
:响铃\b
:退格\n
:换行\r
:回车\t
:制表符
如果想要在命令行使用这些不可打印的字符,可以把它们放在引号里面,然后使用echo
命令的-e
参数。
|
|
由于反斜杠可以对换行符转义,使得 Bash 认为换行符是一个普通字符,从而可以将一行命令写成多行。
|
|
如果一条命令过长,就可以在行尾使用反斜杠,将其改写成多行。这是常见的多行命令的写法。
2.单引号
Bash允许字符串放在单引号或双引号之中,加以引用.
单引号用于保留字符的字面含义,各种特殊字符在单引号里面,都会变为普通字符,比如星号(*
)、美元符号($
)、反斜杠(\
)等。
|
|
3.双引号
双引号比单引号宽松,可以保留大部分特殊字符的本来含义,但是三个字符除外:美元符号($
)、反引号(```)和反斜杠(\
)。也就是说,这三个字符在双引号之中,会被 Bash 自动扩展。
双引号会保存原始命令的输出格式.
|
|
如果$(cal)
不放在双引号之中,echo
就会将所有结果以单行输出,丢弃了所有原始的格式。
4.Here文档
Here文档是一种输入多行字符串的方法,格式如下
|
|
它的格式分成开始标记(<< token
)和结束标记(token
)。开始标记是两个小于号 + Here 文档的名称,名称可以随意取,后面必须是一个换行符;结束标记是单独一行顶格写的 Here 文档名称,如果不是顶格,结束标记不起作用。两者之间就是多行字符串的内容。
|
|
Here 文档的开始标记(_example_
)放在单引号之中,导致变量替换失效了。
5.Here字符串
Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(<<<
)表示。
|
|
它的作用是将字符串通过标准输入,传递给命令。
Bash变量
简介
Bash变量分成环境变量和自定义变量两类
环境变量是 Bash 环境自带的变量,进入 Shell 时已经定义好了,可以直接使用。它们通常是系统定义好的,也可以由用户从父 Shell 传入子 Shell。
env
命令或printenv
命令,可以显示所有环境变量。
下面是一些常见的环境变量。
BASHPID
:Bash 进程的进程 ID。BASHOPTS
:当前 Shell 的参数,可以用shopt
命令修改。DISPLAY
:图形环境的显示器名字,通常是:0
,表示 X Server 的第一个显示器。EDITOR
:默认的文本编辑器。HOME
:用户的主目录。HOST
:当前主机的名称。IFS
:词与词之间的分隔符,默认为空格。LANG
:字符集以及语言编码,比如zh_CN.UTF-8
。PATH
:由冒号分开的目录列表,当输入可执行程序名后,会搜索这个目录列表。PS1
:Shell 提示符。PS2
: 输入多行命令时,次要的 Shell 提示符。PWD
:当前工作目录。RANDOM
:返回一个0到32767之间的随机数。SHELL
:Shell 的名字。SHELLOPTS
:启动当前 Shell 的set
命令的参数,参见《set 命令》一章。TERM
:终端类型名,即终端仿真器所用的协议。UID
:当前用户的 ID 编号。USER
:当前用户的用户名。
很多环境变量很少发生变化,而且是只读的,可以视为常量。由于它们的变量名全部都是大写,所以传统上,如果用户要自己定义一个常量,也会使用全部大写的变量名。
注意,Bash 变量名区分大小写,HOME
和home
是两个不同的变量。
创建变量
用户创建变量的时候,变量名必须遵守下面的规则。
- 字母、数字和下划线字符组成。
- 第一个字符必须是一个字母或一个下划线,不能是数字。
- 不允许出现空格和标点符号。
变量声明的语法如下:
|
|
Bash没有数据类型的概念,所有的变量值都是字符串
自定义变量的例子
|
|
3.读取变量
读取变量的时候,直接在变量名前加上$就可以了
如果变量不存在,Bash不会报错,而会输出空字符.
如果变量的值本身也是变量,可以使用${!varname}
的语法,读取最终的值.
$ myvar=USER
$ echo ${!myvar}
ruanyf
4.删除变量
unset
命令用来删除一个变量。
删除一个变量,也可以将这个变量设成空字符串。
5.输出变量,export命令
export命令用来向子shell输出变量.
|
|
6.特殊变量
Bash提供了一些特殊变量,这些变量的值由Shell提供,用户不能进行赋值.
$?
:上一个命令的退出码,用来判断上一个命令是否执行成功. 0 为成功,非0,则失败$$
:为当前Shell的进程ID
这个图书编了可以用来命名临时文件.
LOGFILE=/tmp/output_log.$$
-
$_
:上个命令的最后一个参数 -
$!
为最近一个后台执行的异步命令的进程ID -
$0
:为当前Shell的名称(在命令行直接执行时)或脚本名(在脚本中执行时) -
$-
:为当前Shell的启动参数 -
$@
和$#
表示脚本的参数数量
7.变量的默认值
Bash提供四个特殊语法,跟变量的默认值有关,目的是保证变量不为空.
|
|
8.declare命令
declare命令可以声明一些特殊类型的变量,为变量设置一些限制,比如声明只读类型的变量和整数类型的变量
语法如下
declare OPTION VARIABLE=value
declare
命令的主要参数(OPTION)如下。
-a
:声明数组变量。-f
:输出所有函数定义。-F
:输出所有函数名。-i
:声明整数变量。-l
:声明变量为小写字母。-p
:查看变量信息。-r
:声明只读变量。-u
:声明变量为大写字母。-x
:该变量输出为环境变量。
declare命令如果用在函数中,声明的变量只在函数内部有效,等同于local命令
不带任何参数时,declare命令输出当前环境的所有变量,包括函数在内,等同于不带有任何参数的set命令
9.readonlymingling
readonly
命令等同于declare -r
,用来声明只读变量,不能改变变量值,也不能unset
变量。
|
|
更改只读变量foo
会报错,命令执行失败。
readonly
命令有三个参数。
-f
:声明的变量为函数名。-p
:打印出所有的只读变量。-a
:声明的变量为数组。
10.let命令
let命令声明变量时,可以直接执行算数表达式
|
|
字符串操作
1. 字符串的长度
获取字符串长度的语法
|
|
大括号{}
是必需的,否则 Bash 会将$#
理解成脚本的参数个数,将变量名理解成文本。
2.子字符串
字符串提取子串的语法
|
|
上面语法的含义是返回变量$varname
的子字符串,从位置offset
开始(从0
开始计算),长度为length
。
|
|
3.搜索和替换
Bash 提供字符串搜索和替换的多种方法。
(1)字符串头部的模式匹配。
|
|
(2)字符串尾部的模式匹配。
(3)任意位置的模式匹配。
4.改变大小写
下面的语法可以改变变量的大小写。
|
|
Bash算术运算
1.算术表达式
((...))
语法可以进行整数的算术运算。
|
|
((...))
语法支持的算术运算符如下。
+
:加法-
:减法*
:乘法/
:除法(整除)%
:余数**
:指数++
:自增运算(前缀或后缀)--
:自减运算(前缀或后缀)
|
|
3.位运算
$((...))
支持以下的二进制位运算符。
<<
:位左移运算,把一个数字的所有位向左移动指定的位。>>
:位右移运算,把一个数字的所有位向右移动指定的位。&
:位的“与”运算,对两个数字的所有位执行一个AND
操作。|
:位的“或”运算,对两个数字的所有位执行一个OR
操作。~
:位的“否”运算,对一个数字的所有位取反。!
:逻辑“否”运算^
:位的异或运算(exclusive or),对两个数字的所有位执行一个异或操作。
4.逻辑运算
$((...))
支持以下的逻辑运算符。
<
:小于>
:大于<=
:小于或相等>=
:大于或相等==
:相等!=
:不相等&&
:逻辑与||
:逻辑或expr1?expr2:expr3
:三元条件运算符。若表达式expr1
的计算结果为非零值(算术真),则执行表达式expr2
,否则执行表达式expr3
。
如果逻辑表达式为真,返回1
,否则返回0
。
|
|
三元运算符执行一个单独的逻辑测试。它用起来类似于if/then/else
语句。
|
|
5.赋值运算
算术表达式$((...))
可以执行赋值运算。
|
|
6.求值运算
逗号,
在$((...))
内部是求值运算符,执行前后两个表达式,并返回后一个表达式的值。
|
|
7.expr命令
expr
命令支持算术运算,可以不使用((...))
语法。
|
|
目录堆栈
1.cd-
Bash 可以记忆用户进入过的目录。默认情况下,只记忆前一次所在的目录,cd -
命令可以返回前一次的目录。
|
|
用户原来所在的目录是/path/to/foo
,进入子目录bar
以后,使用cd -
可以回到原来的目录。
2.pushd,popd
pushd
命令时,会将当前目录先放入堆栈,然后将所要进入的目录也放入堆栈,位置在前一个记录的上方。以后每次使用pushd
命令,都会将所要进入的目录,放在堆栈的顶部。
popd
命令不带有参数时,会移除堆栈的顶部记录,并进入新的堆栈顶部目录(即原来的第二条目录)。
3. dirs
操作目录堆栈的内容
Bash脚本入门
脚本(script)就是包含一系列命令的一个文本文件。Shell 读取这个文件,依次执行里面的所有命令,就好像这些命令直接输入到命令行一样。所有能够在命令行完成的任务,都能够用脚本完成。
1.Shebang行
脚本的第一行通常是指定解释器,也就是通过什么解释器执行.
#!
后面就是脚本解释器的位置,Bash 脚本的解释器一般是/bin/sh
或/bin/bash
。
|
|
如果 Bash 解释器不放在目录/bin
,脚本就无法执行了。为了保险,可以写成下面这样。
#!/usr/bin/env bash
2.执行权限和路径
前面说过,只要指定了 Shebang 行的脚本,可以直接执行。这有一个前提条件,就是脚本需要有执行权限。可以使用下面的命令,赋予脚本执行权限
|
|
脚本的权限通常设为755
(拥有者有所有权限,其他人有读和执行权限)或者700
(只有拥有者可以执行)。
除了执行权限,脚本调用时,一般需要指定脚本的路径(比如path/script.sh
)。如果将脚本放在环境变量$PATH
指定的目录中,就不需要指定路径了。因为 Bash 会自动到这些目录中,寻找是否存在同名的可执行文件。
建议在主目录新建一个~/bin
子目录,专门存放可执行脚本,然后把~/bin
加入$PATH
。
export PATH=$PATH:~/bin
命令改变环境变量$PATH
,将~/bin
添加到$PATH
的末尾。可以将这一行加到~/.bashrc
文件里面,然后重新加载一次.bashrc
,这个配置就可以生效了。
$ source ~/.bashrc
以后不管在什么目录,直接输入脚本文件名,脚本就会执行。
3.env命令
env
命令总是指向/usr/bin/env
文件,或者说,这个二进制文件总是在目录/usr/bin
。
#!/usr/bin/env NAME
这个语法的意思是,让 Shell 查找$PATH
环境变量里面第一个匹配的NAME
。如果你不知道某个命令的具体路径,或者希望兼容其他用户的机器,这样的写法就很有用。
env
命令的参数如下。
-i
,--ignore-environment
:不带环境变量启动。-u
,--unset=NAME
:从环境变量中删除一个变量。--help
:显示帮助。--version
:输出版本信息。
4.注释
Bash 脚本中,#
表示注释,可以放在行首,也可以放在行尾。
5.脚本参数
调用脚本的时候,脚本文件名后面可以带有参数
$ script.sh word1 word2 word3
脚本文件内部,可以使用特殊变量,引用这些参数。
$0
:脚本文件名,即script.sh
。$1
~$9
:对应脚本的第一个参数到第九个参数。$#
:参数的总数。$@
:全部的参数,参数之间使用空格分隔。$*
:全部的参数,参数之间使用变量$IFS
值的第一个字符分隔,默认为空格,但是可以自定义。
如果多个参数放在双引号里面,视为一个参数。
6.shift命令
shift
命令可以改变脚本参数,每次执行都会移除脚本当前的第一个参数($1
),使得后面的参数向前一位,即$2
变成$1
、$3
变成$2
、$4
变成$3
,以此类推。
while
循环结合shift
命令,也可以读取每一个参数。]
|
|
shift
命令可以接受一个整数作为参数,指定所要移除的参数个数,默认为1
。
7.getopts命令
getopts
命令用在脚本内部,可以解析复杂的脚本命令行参数,通常与while
循环一起使用,取出脚本所有的带有前置连词线(-
)的参数。
getopts optstring name
它带有两个参数。第一个参数optstring
是字符串,给出脚本所有的连词线参数。比如,某个脚本可以有三个配置项参数-l
、-h
、-a
,其中只有-a
可以带有参数值,而-l
和-h
是开关参数,那么getopts
的第一个参数写成lha:
,顺序不重要。注意,a
后面有一个冒号,表示该参数带有参数值,getopts
规定带有参数值的配置项参数,后面必须带有一个冒号(:
)。getopts
的第二个参数name
是一个变量名,用来保存当前取到的配置项参数,即l
、h
或a
。
|
|
while
循环不断执行getopts 'lha:' OPTION
命令,每次执行就会读取一个连词线参数(以及对应的参数值),然后进入循环体。变量OPTION
保存的是,当前处理的那一个连词线参数(即l
、h
或a
)。如果用户输入了没有指定的参数(比如-x
),那么OPTION
等于?
。循环体内使用case
判断,处理这四种不同的情况。
8.配置项参数终止符
变量当作命令的参数时,有时希望指定变量只能作为实体参数,不能当作配置项参数,这时可以使用配置项参数终止符--
。
|
|
9.exit命令
exit
命令用于终止当前脚本的执行,并向 Shell 返回一个退出值。
|
|
退出时,脚本会返回一个退出值。脚本的退出值,0
表示正常,1
表示发生错误,2
表示用法不对,126
表示不是可执行脚本,127
表示命令没有发现。如果脚本被信号N
终止,则退出值为128 + N
。简单来说,只要退出值非0,就认为执行出错。
10.命令执行结果
命令执行结束后,会有一个返回值。0
表示执行成功,非0
(通常是1
)表示执行失败。环境变量$?
可以读取前一个命令的返回值。
利用这一点,可以在脚本中对命令执行结果进行判断。
|
|
11.source命令
source
命令用于执行一个脚本,通常用于重新加载一个配置文件。
$ source .bashrc
source
命令最大的特点是在当前 Shell 执行脚本,不像直接执行脚本时,会新建一个子 Shell。所以,source
命令执行脚本时,不需要export
变量。
source
有一个简写形式,可以使用一个点(.
)来表示。
12.别名,alias命令
alias
命令用来为一个命令指定别名,这样更便于记忆。下面是alias
的格式。
alias NAME=DEFINITION
|
|
alias
定义的别名也可以接受参数,参数会直接传入原始命令。
|
|
unalias
命令可以解除别名。
直接调用alias
命令,可以显示所有别名。
read命令
脚本需要在执行过程中,由用户提供一部分数据,这时可以使用read命令。它将用户的输入存入一个变量,方便后面的代码使用。用户按下回车键,就表示输入结束。
read命令的格式如下。
read [-options] [variable...]
|
|
条件判断
if结构
语法如下
|
|
test命令
|
|
上面的expression是一个表达式。这个表达式为真,test命令执行成功(返回值为0);表达式为伪,test命令执行失败(返回值为1)。注意,第二种和第三种写法,[和]与内部的表达式之间必须有空格。
剩余部分_改期继续_