shell 脚本最常见的一个用途就是处理文本文件。检查日志文件、读取配置文件、处理数据元素,shell 脚本可以帮助我们将文本中各种数据的日常处理任务自动化。
sed 和 gawk 工具能够简化数据处理任务。
与普通交互式文本编辑器恰好相反,它是一种轻量级流编辑器。
sed 编辑器可以根据命令来处理数据流中的数据,那些命令要么从命令行中输入,要么存储在一个命令文本文件中。要注意的是,它不仅能够修改文件内容,还能修改命令的结果。
sed 编辑器会执行如下操作:
它会将文件中的每一行数据都进行处理,遍历完毕所有的数据行后,它就会终止。
sed 编辑器只需要对数据流进行一遍处理就可以完成编辑操作,效率比交互式编辑器高,可以快速完成对数据的自动修改。
sed options script file
options | descriptions |
---|---|
-n | 一般sed命令会把所有数据都输出到屏幕,如果加入此选项,则只会把经过sed命令处理的行输出到屏幕 |
-e script | 允许对输入数据应用多条sed命令编辑,将script中指定的命令添加到已有的命令中 |
-f file | 允许对输入数据应用多条sed命令编辑, 将file中指定的命令添加到已有的命令中 |
-i | 用sed修改结果直接修改读取数据的文件,而不是由屏幕输出 |
除了 -i 选项,命令只针对屏幕输出进行修改操作。
script | descriptiongs |
---|---|
a \ | 追加,在当前行后添加一行或多行,添加多行时,除最后一行外,每行末尾需要用 \ 代表数据未完结 |
c \ | 行替换,用c后面的字符串替换原数据行,替换多行时,除最后一行外,每行末尾用 \ 代表数据未完结 |
i \ | 插入,在当前行前插入一行或多行。插入多行时,除最后一行外,每行末尾需要用 \ 代表数据未完结 |
d | 删除指定行 |
p | 输出指定行 |
s | 字符替换,用一个字符串替换另外一个字符串 |
默认情况下,sed编辑器会将指定的命令应用到STDIN输入流上,这样你可以直接将数据通过管道输入sed编辑器处理。
$ echo "This is a test." | sed 's/test/big test/'
This is a big test.
sed 's/test/big test' data.txt
针对文件的每行内容进行处理。
使用 -e 选项。
sed -e 's/brown/green/; s/dog/cat/' data.txt
命令末尾和分号之间不能有空格。
或者也可以采用下面的形式:
sed -e '
s/brown/green/
s/fox/elephant/
s/dog/cat/' data.txt
# script.sed
s/brown/green/
s/fox/elephant/
s/dog/cat/
sed -f script.sed data.txt
一种编程语言。
gawk options program file
options | descriptions |
---|---|
-F fs | 指定行中划分数据字段的字段分隔符 |
-f file | 从指定的文件中读取程序 |
-v variable | 定义 gawk 程序中的一个变量及其默认值 |
-mf N | 指定要处理的数据文件中的最大子段数量 |
-mr N | 指定数据文件中的最大数据行数 |
-W keyword | 指定gawk的兼容模式或警告等级 |
gawk 的强大之处在于它可以写脚本来读取文本行的数据,然后处理并显示数据。
gawk 程序脚本用一对花括号来定义,命令行假定脚本是个单个文本字符串,你需要将脚本放到单引号中。如果没有在命令行上指定文件名,gawk 程序会从 STDIN 接受数据,意味着你还需要手动输入字符串供其处理。
Ctrl +D组合键产生一个 EOF 字符,能够终止字符串的输入。
在文本行中,每个数据字段都是通过字段分隔符划分的。gawk 在读取一行文本时,会用预定义的字段分隔符划分每个数据字段。gawk 中默认的字段分隔符时任意的空白字符(例如空格或制表符)。
#data.txt
One line of test text.
Two lines of test text.
Three lines of test text.
只显示第一个字段的值。
$ gawk '{print $1}' data.txt
One
Two
Three
读取使用 : 分隔符的文件。
gawk -F: '{print $1}' /etc/passwd
gawk 编程语言允许你将多条命令组合成一个正常的程序。
$ echo 'My name is Rich' | gawk '{
$4="Christine"; print $0}'
My name is Christine
gawk '{
$4="Christine"
print $0}'
My name is Rich
My name is Christine
要想退出程序,Ctrl+D。
# script.gawk
{
print $1 "'s home directory is " $6}
gawk -F: -f script.gawk /etc/passwd
# script.gawk
{
text = "'s home directory is "
print $1 text $6
}
gawk 中引用变量并不需要使用美元符。
BEGIN 关键字可以强制 gawk 在读取数据前执行 BEGIN 关键字后指定的程序脚本。
gawk 'BEGIN {print "Hello World!"}'
gawk 'BEGIN {print "The data File Contents"}
{print $0}' data.txt
gawk 'BEGIN {print "The data File Contents"}
{print $0}
END {print "End of File"}' data.txt
从数据文件中生成报告脚本:
# script.gawk
BEGIN {
print "The latest list of users and shells"
print " UserID \t Shell"
print "--------\t---------"
FS=":"
{
print $1 " \t " $7
}
END {
print "This concludes the listing"
}
默认替换只会替换每行出现的第一个文本。
s/pattern/replacement/flags
用 C shell 替换 bash shell。
sed 's!/bin/bash!/bin/csh!' /etc/passwd
感叹号被用作字符串分隔符。
默认情况下,sed 命令会作用于全部行,如果想指定特定行,需要使用行寻址。
sed '2s/dog/cat/' data.txt
只修改第二行文本。
sed '2,3s/dog/cat/' data.txt
指定行区间。
sed '2,$s/dog/cat/' data.txt
从第二行开始的所有行。
还是使用正则表达式好一些。
sed '2{
s/fox/elephant/
s/dog/cat/
}' data.txt
两条命令都会作用在该地址上。
sed '3,${
s/fox/elephant/
s/dog/cat/
}' data.txt
sed 'd' data.txt
删除所有行。
sed '3d' data.txt
删除第三行。
sed '2,3d' data.txt
指定行区间。
sed 编辑器不会修改原始文件,除非你写入原文件。
echo "Test Line 2" | sed "i\Test Line 1"
Test Line 1
Test Line 2
将一个新行插入到数据流第三行前。
sed '3i\
This is an inserted line.' data.txt
$ 符号同样适用。
sed '3c\
This is an inserted line.' data.txt
文本模式修改:
sed '/number 3/c\
This is an inserted line.' data.txt
使用地址区间?
sed '2,3c\
This is an inserted line.' data.txt
sed 编辑器会用一行文本来替换数据流中的两行文本。
可以处理单个字符。
sed 'y/123/789/' data.txt
用7来替换1,用8来替换2,用9来替换3。
echo "this is a test" | sed 'p'
打印包含有匹配文本模式的行:
sed -n '/number 3/p' data.txt
-n 选项可以禁止输出其他行。
sed -n '2,3p' data.txt
sed '=' data.txt
sed -n '/number 4/{
=
p
}' data.txt
命令(l)能够打印数据流中的文本和不可打印的ASCII字符。
sed 'l' data.txt
[address]w filename
w 命令用来向文件写入行。
sed '1,2w test.txt' data.txt
将数据流(data.txt)中的前两行打印到一个文本文件(text.txt)中。
将一个独立文件中的数据插入到数据流中。
[address]r filename
sed '3r data.txt' data.txt