附录 A bash 命令快速指南
本章内容
- bash内建命令
- GNU的其他shell命令
- bash环境变量
如本书所述,bash shell包含很多特性,故可用的命令自然也少不到哪里去。本附录提供了一个简明指南,你可以从中快速查找能在bash命令行或bash shell脚本中使用的功能或命令。
A.1 内建命令
bash shell含有许多常用的命令,这些命令都已经内建在了shell中。在使用这些命令时,执行速度就要快很多。表A-1列出了bash shell中直接可用的内建命令。
表A-1 bash内建命令
| 命 令 | 描 述 |
|---|---|
| : | 扩展参数列表,执行重定向操作 |
| . | 读取并执行指定文件中的命令(在当前shell环境中) |
| alias | 为指定命令定义一个别名 |
| bg | 将作业以后台模式运行 |
| bind | 将键盘序列绑定到一个readline函数或宏 |
| break | 退出for、while、select或until循环 |
| builtin | 执行指定的shell内建命令 |
| caller | 返回活动子函数调用的上下文 |
| cd | 将当前目录切换为指定的目录 |
| command | 执行指定的命令,无需进行通常的shell查找 |
| compgen | 为指定单词生成可能的补全匹配 |
| complete | 显示指定的单词是如何补全的 |
| compopt | 修改指定单词的补全选项 |
| continue | 继续执行for、while、select或until循环的下一次迭代 |
| declare | 声明一个变量或变量类型。 |
| dirs | 显示当前存储目录的列表 |
| disown | 从进程作业表中删除指定的作业 |
| echo | 将指定字符串输出到STDOUT |
| enable | 启用或禁用指定的内建shell命令 |
| eval | 将指定的参数拼接成一个命令,然后执行该命令 |
| exec | 用指定命令替换shell进程 |
| exit | 强制shell以指定的退出状态码退出 |
| export | 设置子shell进程可用的变量 |
| fc | 从历史记录中选择命令列表 |
| fg | 将作业以前台模式运行 |
| getopts | 分析指定的位置参数 |
| hash | 查找并记住指定命令的全路径名 |
| help | 显示帮助文件 |
| history | 显示命令历史记录 |
| jobs | 列出活动作业 |
| kill | 向指定的进程ID(PID)发送一个系统信号 |
| let | 计算一个数学表达式中的每个参数 |
| local | 在函数中创建一个作用域受限的变量 |
| logout | 退出登录shell |
| mapfile | 从STDIN读取数据行,并将其加入索引数组 |
| popd | 从目录栈中删除记录 |
| printf | 使用格式化字符串显示文本 |
| pushd | 向目录栈添加一个目录 |
| pwd | 显示当前工作目录的路径名 |
| read | 从STDIN读取一行数据并将其赋给一个变量 |
| readarray | 从STDIN读取数据行并将其放入索引数组 |
| readonly | 从STDIN读取一行数据并将其赋给一个不可修改的变量 |
| return | 强制函数以某个值退出,这个值可以被调用脚本提取 |
| set | 设置并显示环境变量的值和shell属性 |
| shift | 将位置参数依次向下降一个位置 |
| shopt | 打开/关闭控制shell可选行为的变量值 |
| source | 读取并执行指定文件中的命令(在当前shell环境中) |
| suspend | 暂停shell的执行,直到收到一个SIGCONT信号 |
| test | 基于指定条件返回退出状态码0或1 |
| times | 显示累计的用户和系统时间 |
| trap | 如果收到了指定的系统信号,执行指定的命令 |
| type | 显示指定的单词如果作为命令将会如何被解释 |
| typeset | 声明一个变量或变量类型。 |
| ulimit | 为系统用户设置指定的资源的上限 |
| umask 为新建的文件和目录设置默认权限 | |
| unalias | 删除指定的别名 |
| unset | 删除指定的环境变量或shell属性 |
| wait | 等待指定的进程完成,并返回退出状态码 |
相比外部命令,内建命令提供了更高的性能,但shell中包含的内建命令越多,消耗的内存就会越大,而有些命令几乎永远也不会用到。除此之外,bash shell还包含了一些能够为shell提供扩展功能的外部命令。这些都会在A.2节中讨论。
A.2 常见的 bash 命令
除了内建命令外,bash shell还使用外部命令来让你操控文件系统以及处理文件和目录。表A-2列出了在使用bash shell时会用到的常见外部命令。
表A-2 bash shell外部命令
| 命 令 | 描 述 |
|---|---|
| bzip2 | 采用Burrows-Wheeler块排序文本压缩算法和霍夫曼编码进行压缩 |
| cat | 列出指定文件的内容 |
| chage | 修改指定系统用户账户的密码过期日期 |
| chfn | 修改指定用户账户的备注信息 |
| chgrp | 修改指定文件或目录的默认属组 |
| chmod | 为指定文件或目录修改系统安全权限 |
| chown | 修改指定文件或目录的默认属主 |
| chpasswd | 读取一个包含登录名/密码的文件并更新密码 |
| chsh | 修改指定用户账户的默认shell |
| clear | 从终端仿真器或虚拟控制台终端删除文本 |
| compress | 最初的Unix文件压缩工具 |
| coproc | 在后台模式中生成子shell,并执行指定的命令 |
| cp | 将指定文件复制到另一个位置 |
| crontab | 初始化用户的crontable文件对应的编辑器(如果允许的话) |
| cut | 删除文件行中指定的位置 |
| date | 以各种格式显示日期 |
| df | 显示所有挂载设备的当前磁盘空间使用情况 |
| du | 显示指定文件路径的磁盘使用情况 |
| emacs | 调用emacs文本编辑器 |
| file | 查看指定文件的文件类型 |
| find | 对文件进行递归查找 |
| free | 查看系统上可用的和已用的内存 |
| gawk | 使用编程语言命令的流编辑器 |
| grep | 在文件中查找指定的文本字符串 |
| gedit | 调用GNOME桌面编辑器 |
| getopt | 解析命令选项(包括长格式选项) |
| groups | 显示指定用户的组成员关系 |
| groupadd | 创建新的系统组 |
| groupmod | 修改已有的系统组 |
| gzip | 采用Lempel-Ziv编码的GNU项目压缩工具 |
| head | 显示指定文件内容的开头部分 |
| help | 显示bash内建命令的帮助页面 |
| killall | 根据进程名向运行中的进程发送一个系统信号 |
| kwrite | 调用KWrite文本编辑器 |
| less | 查看文件内容的高级方法 |
| link | 用别名创建一个指向文件的链接 |
| ln | 创建针对指定文件的符号链接或硬链接 |
| ls | 列出目录内容 |
| makewhatis | 创建能够使用手册页关键字进行搜索的whatis数据库 |
| man | 显示指定命令或话题的手册页 |
| mkdir | 在当前目录下创建指定目录 |
| more | 列出指定文件的内容,在每屏数据后暂停下来 |
| mount | 显示虚拟文件系统上挂载的磁盘设备或将磁盘设备挂载到虚拟文件系统上 |
| mv | 重命名文件 |
| nano | 调用nano文本编辑器 |
| nice | 在系统上使用不同优先级来运行命令 |
| passwd | 修改某个系统用户账户的密码 |
| ps | 显示系统上运行中进程的信息 |
| pwd | 显示当前目录 |
| renice | 修改系统上运行中应用的优先级 |
| rm | 删除指定文件 |
| rmdir | 删除指定目录 |
| sed | 使用编辑器命令的文本流行编辑器 |
| sleep | 在指定的一段时间内暂停bash shell操作 |
| sort | 基于指定的顺序组织数据文件中的数据 |
| stat | 显示指定文件的文件统计数据 |
| sudo | 以root用户账户身份运行应用 |
| tail | 显示指定文件内容的末尾部分 |
| tar | 将数据和目录归档到单个文件中 |
| top | 显示活动进程以及其他重要的系统统计数据 |
| touch | 新建一个空文件,或更新一个已有文件的时间戳 |
| umount | 从虚拟文件系统上删除一个已挂载的磁盘设备 |
| uptime | 显示系统已经运行了多久 |
| useradd | 新建一个系统用户账户 |
| userdel | 删除已有系统用户账户 |
| usermod | 修改已有系统用户账户 |
| vi | 调用vim文本编辑器 |
| vmstat | 生成一个详尽的系统内存和CPU使用情况报告 |
| whereis | 显示指定命令的相关文件,包括二进制文件、源代码文件以及手册页 |
| which | 查找可执行文件的位置 |
| who | 显示当前系统中的登录用户 |
| whoami | 显示当前用户的用户名 |
| xargs | 从STDIN中获取数据项,构建并执行命令 |
| zip | Windows下PKZIP程序的Unix版本 |
可以用这些命令在命令行上完成几乎所有的事情。
A.3 环境变量
bash shell还使用了许多环境变量。虽然环境变量不是命令,但它们通常会影响shell命令的执行,所以了解这些shell环境变量很重要。表A-3列出了bash shell中可用的默认环境变量。
表A-3 bash shell环境变量
| 变 量 | 描 述 |
|---|---|
| * | 含有所有命令行参数(以单个文本值的形式) |
| @ | 含有所有命令行参数(以多个文本值的形式) |
| # | 命令行参数数目 |
| ? | 最近使用的前台进程的退出状态码 |
| - | 当前命令行选项标记 |
| $ | 当前shell的进程ID(PID) |
| ! | 最近执行的后台进程的PID |
| 0 | 命令行中使用的命令名称 |
| _ | shell的绝对路径名 |
| BASH | 用来调用shell的完整文件名 |
| BASHOPTS | 允许冒号分隔列表形式的shell选项 |
| BASHPID | 当前bash shell的进程ID |
| BASH_ALIASED | 含有当前所用别名的数组 |
| BASH_ARGC | 当前子函数中的参数数量 |
| BASH_ARGV | 含有所有指定命令行参数的数组 |
| BASH_CMDS | 含有命令的内部散列表的数组 |
| BASH_COMMAND | 当前正在被执行的命令名 |
| BASH_ENV | 如果设置了的话,每个bash脚本都会尝试在运行前执行由该变量定义的起始文件 |
| BASH_EXECUTION_STRING | 在-c命令行选项中用到的命令 |
| BASH_LINENO | 含有脚本中每个命令的行号的数组 |
| BASH_REMATCH | 含有与指定的正则表达式匹配的文本元素的数组 |
| BASH_SOURCE | 含有shell中已声明函数所在源文件名的数组 |
| BASH_SUBSHELL | 当前shell生成的子shell数目 |
| BASH_VERSINFO | 含有当前bash shell实例的主版本号和次版本号的数组 |
| BASH_VERSION | 当前bash shell实例的版本号 |
| BASH_XTRACEFD | 当设置一个有效的文件描述符整数时,跟踪输出生成,并与诊断和错误信息分离开 文件描述符必须设置-x启动 |
| COLUMNS | 含有当前bash shell实例使用的终端的宽度 |
| COMP_CWORD | 含有变量COMP_WORDS的索引值,COMP_WORDS包含当前光标所在的位置 |
| COMP_KEY | 调用补全功能的按键 |
| COMP_LINE | 当前命令行 |
| COMP_POINT | 当前光标位置相对于当前命令起始位置的索引 |
| COMP_TYPE | 补全类型所对应的整数值 |
| COMP_WORDBREAKS | 在进行单词补全时用作单词分隔符的一组字符 |
| COMP_WORDS | 含有当前命令行上所有单词的数组 |
| COMPREPLY | 含有由shell函数生成的可能补全码的数组 |
| COPROC | 含有用于匿名协程I/O的文件描述符的数组 |
| DIRSTACK | 含有目录栈当前内容的数组 |
| EMACS | 如果设置了该环境变量,则shell认为其使用的是emacs shell缓冲区,同时禁止行编辑功能 |
| ENV | 当shell以POSIX模式调用时,每个bash脚本在运行之前都会执行由该环境变量所定 义的起始文件 |
| EUID | 当前用户的有效用户ID(数字形式) |
| FCEDIT | fc命令使用的默认编辑器 |
| FIGNORE | 以冒号分隔的后缀名列表,在文件名补全时会被忽略 |
| FUNCNAME | 当前执行的shell函数的名称 |
| FUNCNEST | 嵌套函数的最高层级 |
| GLOBIGNORE | 以冒号分隔的模式列表,定义了文件名展开时要忽略的文件名集合 |
| GROUPS | 含有当前用户属组的数组 |
| histchars | 控制历史记录展开的字符(最多可有3个) |
| HISTCMD | 当前命令在历史记录中的编号 |
| HISTCONTROL | 控制哪些命令留在历史记录列表中 |
| HISTFILE | 保存shell历史记录列表的文件名(默认是.bash_history) |
| HISTFILESIZE | 保存在历史文件中的最大行数 |
| HISTIGNORE | 以冒号分隔的模式列表,用来决定哪些命令不存进历史文件 |
| HISTSIZE | 最多在历史文件中保存多少条命令 |
| HISTIMEFORMAT | 设置后,决定历史文件条目的时间戳的格式字符串HOSTFILE 含有shell在补全主机名时读取的文件的名称 |
| HOSTNAME | 当前主机的名称 |
| HOSTTYPE | 当前运行bash shell的机器 |
| IGNOREEOF | shell在退出前必须收到连续的EOF字符的数量。如果这个值不存在,默认是1 INPUTRC readline初始化文件名(默认是.inputrc) |
| LANG | shell的语言环境分类 |
| LC_ALL 定义一个语言环境分类, | 它会覆盖LANG变量 |
| LC_COLLATE | 设置对字符串值排序时用的对照表顺序 |
| LC_CTYPE | 决定在进行文件名扩展和模式匹配时,如何解释其中的字符 |
| LC_MESSAGES | 决定解释前置美元符($)的双引号字符串的语言环境设置 |
| LC_NUMERIC | 决定格式化数字时的所使用的语言环境设置 |
| LINENO | 脚本中当前执行代码的行号 |
| LINES | 定义了终端上可见的行数 |
| MACHTYPE | 用“cpu公司系统”格式定义的系统类型 |
| MAILCHECK | shell多久查看一次新邮件(以秒为单位,默认值是60) |
| MAPFILE | 含有mapfile命令所读入文本的数组,当没有给出变量名的时候,使用该环境变量 |
| OLDPWD | shell之前的工作目录 |
| OPTERR | 设置为1时,bash shell会显示getopts命令产生的错误 |
| OSTYPE | 定义了shell运行的操作系统 |
| PIPESTATUS | 含有前台进程退出状态码的数组 |
| POSIXLY_CORRECT | 如果设置了该环境变量,bash会以POSIX模式启动PPID bash shell父进程的PID |
| PROMPT_COMMAND | 如果设置该环境变量,在显示命令行主提示符之前会执行这条命令 |
| PS1 | 主命令行提示符字符串 |
| PS2 | 次命令行提示符字符串 |
| PS3 | select命令的提示符 |
| PS4 | 如果使用了bash的-x选项,在命令行显示之前显示的提示符 |
| PWD | 当前工作目录 |
| RANDOM | 返回一个0~32 767的随机数,对其赋值可作为随机数生成器的种子 |
| READLINE_LINE | 保存了readline行缓冲区中的内容 |
| READLINE_POINT | 当前readline行缓冲区的插入点位置 |
| REPLY | read命令的默认变量 |
| SECONDS | 自shell启动到现在的秒数,对其赋值将会重置计时器 |
| SHELL | shell的全路径名 |
| SHELLOPTS | 已启用bash shell选项列表,由冒号分隔 |
| SHLVL | 表明shell层级,每次启动一个新的bash shell时计数加1 |
| TIMEFORMAT | 指定了shell显示的时间值的格式 |
| TMOUT | select和read命令在没输入的情况下等待多久(以秒为单位)。默认值为零,表示无限长 |
| TMPDIR | 如果设置成目录名,shell会将其作为临时文件目录 |
| UID | 当前用户的真实用户ID(数字形式) |
可以用set内建命令来显示这些环境变量。对于不同的Linux发行版,开机时设置的默认shell 环境变量经常会不一样。
附录 B sed 和 gawk 快速指南
本章内容
- sed编辑器基础
- gawk必知必会
如果要在shell脚本中进行数据处理,很可能需要使用sed或gawk程序(有时两者都要用)。本附录提供了一份sed和gawk的快速参考。在shell脚本中处理数据时,这应该能派上用场。
B.1 sed 编辑器
sed编辑器可以基于命令来操作数据流中的数据,这些命令要么从命令行中输入,要么保存在命令文本文件中。它每次从输入中读取一行数据,并用提供的编辑器命令匹配该数据,按命令中指定的操作修改数据,然后将生成的新数据输出到STDOUT。
B.1.1 启动 sed 编辑器
sed命令的格式如下:
sed options script file
options参数允许你定制sed命令的行为,可包含表B-1中所列的选项。
表B-1 sed命令选项
| 选 项 | 描 述 |
|---|---|
| -e script | 将script中指定的命令添加到处理输入时运行的命令中 |
| -f file | 将file文件中指定的命令添加到处理输入时运行的命令中 |
| -n | 不要为每条命令产生输出,但会等待打印命令 |
script参数指定了作用在数据流上的单条命令。如果需要不止一条命令,要么用-e选项在 命令行上指定它们,要么用-f选项在一个单独文件中指定它们。
B.1.2 sed 命令
sed编辑器脚本含有sed针对输入流中的每行数据执行的命令。本节将会介绍一些较常见的sed命令。
- 替换
s命令会替换输入流中的文本。s命令的格式如下。
s/pattern/replacement/flags
其中pattern是要被替换的文本,replacement是sed要插到数据流中的新文本。
flags参数控制如何进行替换。有4种类型的替换标记可用。
- 一个数字,表明该模式出现的第几处应该被替换。
- g:表明所有该文本出现的地方都应该被替换。
- p:表明原来行中的内容应该被打印出来。
- w file:表明替换的结果应该写入到文件file中。
在第一类替换中,你可以指定sed编辑器应该替换第几处匹配模式的地方。举个例子,你可以用数字2来只替换该模式第二次出现的地方。
- 寻址
默认情况下,你在sed编辑器中使用的命令会作用在文本数据的所有行上。如果你想让命令只作用在指定行或一组行上,就必须使用行寻址(line addressing)。
在sed编辑器中,有两种形式的行寻址:
- 行区间(数字形式)
- 可以过滤出特定行的文本模式
两种形式使用相同的格式来指定地址。
[address]command
当使用数字形式的行寻址时,我们通过行在文本流中的位置来引用行。sed编辑器会给数据流中的第一行分配行号1,然后对接下来的每行依次顺序增加。
$ sed '2,3s/dog/cat/' data1
另一个限制命令作用在哪些行上的方法有点复杂。sed编辑器允许你指定一个文本模式,它会用这个文本模式来为命令过滤出行,格式如下。
/pattern/command
必须用斜线来将你指定的pattern包围起来。sed编辑器会将command只作用在包含你指定 的文本模式的行上。
$ sed '/rich/s/bash/csh/' /etc/passwd
这个过滤器能够找到含有文本rich的行,然后用csh来替换文本bash。也可以为某个特定地址将多条命令放在一起。
address {
command1
command2
command3 }
sed编辑器会将你指定的每条命令作用在匹配指定地址的行上。sed编辑器会处理和地址行对应的每条命令。
$ sed '2{
> s/fox/elephant/
> s/dog/cat/
> }' data1
sed编辑器将每一条替换命令都作用在数据文件的第二行上。
- 删除行
删除(delete)命令d与它的名字十分相配。它会删除所有与提供的地址模式匹配的文本行。使用删除命令时要小心,因为如果你忘记加地址模式,所有的行都会被从数据流中删掉。
$ sed 'd' data1
显然,删除命令跟指定的地址一起使用时才最有用。它允许你从数据流中删除特定的文本行, 要么通过行号指定:
$ sed '3d' data6
要么通过特定的行区间指定:
$ sed '2,3d' data6
sed编辑器的模式匹配功能也适用于删除命令。
$ sed '/number 1/d' data6
只有匹配指定文本的行才会被从流中删掉。
- 插入和附加文本
如你所料,跟任何其他编辑器一样,sed编辑器允许你向数据流中插入和附加文本。这两个命令的区别有些模糊:
- 插入(insert)命令(i)在指定行前面添加一个新行;
- 附加(append)命令(a)在指定行后面添加一个新行。
这两条命令的格式很容易让人困惑:你不能在单个命令行上使用这两条命令。要插入或附加的行必须作为单独的一行出现,格式如下。
sed '[address]command\ new line'
new line中的文本按你指定的位置出现在sed编辑器的输出中。记住,当使用插入命令时, 文本会出现在指定行之前。
$ echo "testing" | sed 'i\
> This is a test'
This is a test
testing
$
当使用追加命令时,文本会出现在指定行之后。
$ echo "testing" | sed 'a\
> This is a test'
testing
This is a test
$
这允许你在普通文本的末尾插入文本。
- 修改行
修改(change)命令允许你修改数据流中的整行文本。其格式跟插入和附加命令一样,你必须将新行与sed命令的其余部分分开。
$ sed '3c\
> This is a changed line of text.' data6
反斜线字符用来表明脚本中的新数据行。
- 转换命令
转换(transform)命令(y)是唯一一个作用在单个字符上的sed编辑器命令。转换命令使用如下格式。
[address]y/inchars/outchars/
转换命令对inchars和outchars执行一对一的映射。inchars中的第一个字符会转换为outchars中的第一个字符,inchars中的第二个字符会转换为outchars中的第二个字符,依此 类推,直到超过了指定字符的长度。如果inchars和outchars长度不同,sed编辑器会报错。
- 打印行
类似于替换命令中的p标记,p命令会在sed编辑器的输出中打印一行。打印(print)命令 最常见的用法是打印与指定文本模式匹配的文本行。
$ sed -n '/number 3/p' data6
This is line number 3.
$
打印命令允许你从输入流中过滤出特定的数据行。
- 写入到文件
w命令用来将文本行写入到文件中。w命令的格式为:
[address]w filename
filename可以用相对路径或绝对路径指定,但不管怎样,运行sed编辑器的人都必须有文件的写权限。address可以是任意类型的寻址方法,比如单行行号、文本模式、行号区间或多个文本模式。
这里有个例子,它只将数据流的前两行写入到文本文件。
$ sed '1,2w test' data6
输出文件test只含有输入流的前两行。
- 从文件中读取
你已经了解了如何使用sed命令向数据流中插入和附加文本。读取(read)命令(r)允许你插入单个文件中的数据。读取命令的格式为:
[address]r filename
其中filename参数使用相对路径或绝对路径的形式来指定含有数据的文件。读取命令不能使用地址区间,只能使用单个行号或文本模式地址。sed编辑器会将文件中的文本插入指定地址之后:
$ sed '3r data' data2
sed编辑器将data文件中的全部文本都插入了data2文件中第3行开始的地方。
B.2 gawk 程序
gawk程序是Unix上最初的awk程序的GNU版本。相较于sed编辑器使用的编辑器命令,awk 程序采用了编程语言的形式,将流编辑又推进了一步。作为一份gawk功能的快速参考,本节将介绍gawk程序的基础知识。
B.2.1 gawk 命令格式
gawk程序的基本格式如下。
gawk options program file
表B-2列出了gawk程序支持的选项。
表B-2 gawk选项
| 选 项 | 描 述 |
|---|---|
| -F fs | 指定用于分隔行中数据字段的文件分隔符 |
| -f file | 指定要读取的程序文件名 |
| -v var=value | 定义gawk程序中的一个变量及其默认值 |
| -mf N | 指定要处理的数据文件中的最大字段数 |
| -mr N | 指定数据文件中的最大记录数 |
| -W keyword | 指定gawk的兼容模式或警告等级。用help选项来列出所有可用的关键字 |
可以使用命令行选项轻松地定制gawk程序的功能。
B.2.2 使用 gawk
可以直接从命令行或shell脚本中使用gawk。本节将会演示如何使用gawk程序以及如何编写由gawk处理的脚本。
- 从命令行上读取程序脚本
gawk程序脚本是由一对花括号定义的。你必须将脚本命令放在两个花括号之间。由于gawk 命令行假定脚本是一个文本字符串,你还必须用单引号来将脚本圈起来。下面是一个在命令行上指定的简单的gawk程序脚本。
$ gawk '{print $1}'
这个脚本会显示输入流中每行的第一个数据字段。
- 在程序脚本中使用多条命令
如果只能执行一条命令的话,这门编程语言也没多大用处。gawk编程语言允许你将多条命令组合成一个普通的程序。要在命令行上指定的程序脚本中使用多条命令,只需在每个命令之间放一个分号就可以了。
$ echo "My name is Rich" | gawk '{$4="Dave"; print $0}'
My name is Dave
$
该脚本执行了两条命令:先用一个不同的值替换第四个数据字段,再显示流中的整个数据行。
- 从文件中读取程序
跟sed编辑器一样,gawk编辑器允许你将程序存储在文件中,然后在命令行上引用它们。
$ cat script2
{ print $5 "'s userid is " $1 }
$ gawk -F: -f script2 /etc/passwd
gawk程序在输入数据流上执行了文件中指定的所有命令。
- 在处理数据前运行脚本
gawk程序还允许你指定程序脚本何时运行。默认情况下,gawk从输入中读取一行文本,然后对这行文本中的数据执行程序脚本。有时,你可能需要在处理数据之前(比如创建报告的标题) 运行脚本。为了做到这点,可以使用BEGIN关键字。它会强制gawk先执行BEGIN关键字后面指定的程序脚本,然后再读取数据。
$ gawk 'BEGIN {print "This is a test report"}'
This is a test report
$
可以在BEGIN块中放置任何类型的gawk命令,比如给变量赋默认值。
- 在处理数据后运行脚本
类似于BEGIN关键字,END关键字允许你指定一个程序脚本,在gawk读取数据后执行。
$ gawk 'BEGIN {print "Hello World!"} {print $0} END {print
"byebye"}' data1
Hello World!
This is a test
This is a test
This is another test.
This is another test.
byebye
$
gawk程序会先执行BEGIN块中的代码,然后处理输入流中的数据,最后执行END块中的代码。
B.2.3 gawk 变量
gawk程序不只是一个编辑器,还是一个完整的编程环境。正因为如此,有大量的命令和特性和gawk息息相关。本节将为你介绍使用gawk编程时需要知道的一些主要功能。
- 内建变量
gawk程序使用内建变量来引用程序数据中特定特性。本节将会为你介绍可用于gawk程序中的内建变量及其用法。
gawk程序将数据定义成记录和数据字段。记录是一行数据(默认用换行符分隔),而数据字段则是行中独立的数据元素(默认用空白字符分隔,比如空格或制表符)。
gawk程序使用数据字段来引用每条记录中的数据元素。表B-3描述了这些变量。
表B-3 gawk数据字段和记录变量
| 变 量 | 描 述 |
|---|---|
| $0 | 整条记录 |
| $1 | 记录中的第1个数据字段 |
| $2 | 记录中的第2个数据字段 |
| $n | 记录中的第n个数据字段 |
| FIELDWIDTHS | 一列由空格分隔的数字,定义了每个字段具体宽度 |
| FS | 输入字段分隔符 |
| RS | 输入记录分隔符 |
| OFS | 输出字段分隔符 |
| ORS | 输出字段分隔符 |
除了字段和记录分隔符变量,gawk还提供了其他一些内建变量,可以帮助你了解数据的相关情况以及从shell环境中提取信息。表B-4介绍了gawk中其他的内建变量。
表B-4 更多的gawk内建变量
| 变 量 | 描 述 |
|---|---|
| ARGC | 当前命令行参数个数 |
| ARGIND | 当前文件在ARGV中的索引 |
| ARGV | 包含命令行参数的数组 |
| CONVFMT | 数字的转换格式(参见printf语句),默认值为%.6g |
| ENVIRON | 由当前shell环境变量及其值组成的关联数组 |
| ERRNO | 当读取或关闭输入文件发生错误时的系统错误号 |
| FILENAME | 用作gawk输入的数据文件的文件名 |
| FNR | 当前数据文件中的记录数 |
| IGNORECASE | 设成非零时,忽略gawk命令中出现的字符串的字符大小写 |
| NF | 数据文件中的字段总数 |
| NR | 已处理的输入记录数 |
| OFMT | 数字的输出格式,默认值为%.6g |
| RLENGTH | 由match函数所匹配的子串的长度 |
| RSTART | 由match函数所匹配的子串的起始位置 |
可以在gawk程序脚本中的任何地方使用内建变量,包括BEGIN和END代码块中。
- 在脚本中给变量赋值
在gawk程序中给变量赋值类似于在shell脚本中给变量赋值,两者都使用赋值语句。
$ gawk '
> BEGIN{
> testing="This is a test"
> print testing
> }'
This is a test
$
给变量赋值后,就可以在gawk脚本中任何地方使用该变量了。
- 在命令行上给变量赋值
也可以用gawk命令行为gawk程序给变量赋值。这允许你在正常代码外设置值,即时修改值。下面的例子使用命令行变量来显示文件中特定数据字段。
$ cat script1
BEGIN{FS=","}
{print $n}
$ gawk -f script1 n=2 data1
$ gawk -f script1 n=3 data1
这个特性是在gawk脚本中处理shell脚本数据的一个好办法。
B.2.4 gawk 程序的特性
gawk程序有一些特性使它非常便于数据操作,允许你创建gawk脚本来解析包括日志文件在内的几乎任何类型的文本文件。
- 正则表达式
可使用基础正则表达式(BRE)或扩展正则表达式(ERE)将程序脚本要处理的行过滤出来。在使用正则表达式时,正则表达式必须出现在它所作用的程序代码的左花括号之前。
$ gawk 'BEGIN{FS=","} /test/{print $1}' data1
This is a test
$
- 匹配操作符
匹配操作符(matching operator)允许你将正则表达式限定在数据行中的特定数据字段上。匹配操作符是波浪线(~)。你可以指定匹配操作符、数据字段变量以及要匹配的正则表达式。
$1 ~ /^data/
这个表达式会过滤出第一个数据字段以文本data开头的记录。
- 数学表达式
除了正则表达式外,还可以在匹配模式中使用数学表达式。这个功能在匹配数据字段中的数字值时非常有用。举个例子,如果你要显示所有属于root用户组(组ID为0)的系统用户,可以使用如下脚本。
$ gawk -F: '$4 == 0{print $1}' /etc/passwd
这个脚本显示出第四个数据字段含有值0的所有行的第一个数据字段。
- 结构化命令
gawk程序支持本节讨论的如下结构化命令。
if-then-else语句:
if (condition) statement1; else statement2
while语句:
while (condition)
{
statements
}
do-while语句:
do {
statements
} while (condition)
for语句:
for(variable assignment; condition; iteration process)
这为gawk脚本程序员提供了大量的编程手段。可以利用它们编写出能够媲美其他高级语言程序功能的gawk程序。
