【Linux命令行与Shell脚本编程】第十八章 文本处理与编辑器基础

Linux命令行与Shell脚本编程

第十八章 文本处理与编辑器基础

文章目录


文本处理与编辑器基础

  • 文本处理
  • 学习sed编辑器
  • sed编辑器基础命令
  • gawk编辑器入门
  • sed编辑器基础

shell脚本可以将文本文件中各种数据的日常处理任务自动化Linux中的sed和gawk两款工具能够极大地简化数据处理任务。

8.1.文本处理

想要即时处理文本文件中的文本,有一个可以自动格式化、插入、修改或删除文本元素的简单的命令行编辑器。

有两款常见工具sed和gawk。

8.1.1.sed编辑器

sed编辑器(stream editor)流编辑器.

在交互式文本编辑器(比如Vim)中,可以用键盘命令交互式地插入、删除或替换文本数据。

流编辑器则是根据事先设计好的一组规则编辑数据流。

sed编辑器根据命令来处理数据流中的数据,命令可以从命令行中输入,可以保存在命令文本文件中.

sed编辑器可以执行下列操作:

  1. 从输入中读取一行数据。
  2. 根据所提供的编辑器命令匹配数据。
  3. 按照命令修改数据流中的数据。
  4. 将新的数据输出到STDOUT。

在流编辑器匹配并对一行数据执行所有命令后,会读取下一行数据并重复执行。在流编辑器处理完数据流中的所有行后,就结束运行。

sed命令格式:

js 复制代码
sed options script file

options参数允许修改sed命令的行为:

选项 描述
-e commands 处理输入时,加入额外的sed命令
-f file 处理输入时,将file中指定的命令添加到已有命令中
-n 不产生输出,使用p(print)命令完成输出

script参数指定了应用于流数据中的单个命令。

如果需要多个命令,则使用-e选项在命令行中指定,或使用-f选项在单独的文件中指定。

8.1.1.1.在命令行中定义编辑器命令

默认情况下,sed编辑器会将指定的命令应用于STDIN输入流中。因此,可以直接将数据通过管道传入sed编辑器进行处理.

s 替换命令:替换命令会用斜线间指定的第二个字符串替换第一个字符串。

js 复制代码
$ echo "This is a test" | sed 's/test/big test/'
This is a big test

sed编辑器的强大之处是可以同时对数据做出多处修改.

js 复制代码
$ cat data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$ sed 's/dog/cat/' data1.txt
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.

sed命令几乎瞬间就执行完毕并返回数据。在处理每行数据的同时,结果也随之显现。在sed编辑器处理完整个文件之前就能看到结果。

重要的是sed编辑器并不会修改文本文件的数据。它只是将修改后的数据发送到STDOUT !!!

8.1.1.2.在命令行中使用多个编辑器命令

使用-e选项在sed命令行中执行多个命令.

js 复制代码
$ sed -e 's/brown/red/; s/dog/cat/' data1.txt
The quick red fox jumps over the lazy cat.
The quick red fox jumps over the lazy cat.
The quick red fox jumps over the lazy cat.
The quick red fox jumps over the lazy cat.

命令之间必须以分号 ; 分隔,命令末尾和分号之间不能出现空格。

也可以用bash shell中的次提示符来分隔命令。输入第一个单引号标示出sed程序脚本的起始.

要在闭合单引号所在行结束命令。bash shell一旦发现了闭合单引号,就会执行命令.

js 复制代码
$ sed -e '
> s/brown/green/
> s/fox/toad/
> s/dog/cat/' data1.txt
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.

8.1.1.3.从文件中读取编辑器命令

将量要执行的sed命令放进单独的文件通常会更方便.

在sed命令中用-f选项来指定文件:

js 复制代码
$ cat script1.sed
s/brown/green/
s/fox/toad/
s/dog/cat/
$ sed -f script1.sed data1.txt
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.
The quick green toad jumps over the lazy cat.

不用在每条命令后面加分号。sed编辑器将每一行作为一条单独的命令。

sed编辑器脚本文件容易与bash shell脚本文件混淆。可以使用.sed作为sed脚本文件的扩展名。

更多sed命令 sed编辑器基础命令

8.1.2.gawk编辑器

虽然sed编辑器非常方便,可以即时修改文本文件,但其自身也存在一些局限。

往往还需要一款更高级的文本文件处理工具能够提供一个更贴近编程的环境,修改和重新组织文件中的数据。

gawk是Unix中最初的awk的GNU版本。gawk比sed的流编辑提升了一个"段位",提供了一种编程语言而不仅仅是编辑器命令。

在gawk编程语言中,可以实现:

  • 定义变量来保存数据。
  • 使用算术和字符串运算符来处理数据。
  • 使用结构化编程概念(比如if-then语句和循环)为数据处理添加处理逻辑。
  • 提取文件中的数据将其重新排列组合,最后生成格式化报告。

gawk的报告生成能力多用于从大文本文件中提取数据并将其格式化成可读性报告。

最完美的应用案例是格式化日志文件。gawk能够从日志文件中过滤出所需的数据,将其格式化,以便让重要的数据更易于阅读。

8.1.2.1.gawk命令格式

js 复制代码
gawk options program file
选项 描述
-F fs 指定行中划分数据字段的字段分隔符
-f file 从指定文件中读物gawk脚本代码
-v var=value 定义gawk脚本中的变量与默认值
-L [keyword] 指定gawk的兼容模式或警告级别

gawk可以编写脚本来读取文本行中的数据,然后对其进行处理并显示,形成各种输出报告。

8.1.2.2.从命令行读取gawk脚本

gawk脚本用一对花括号来定义。必须将脚本命令放到一对单引号与花括号 '{}' 之间。

gawk命令行假定脚本是单个文本字符串,因此必须将脚本放到单引号中。

没有在命令行中指定文件名时,gawk程序会从STDIN接收数据。在脚本运行时,会一直等待来自STDIN的文本。

js 复制代码
$ gawk '{print "Hello World!"}'
This is a test
Hello World!
hello
Hello World!
Goodbye
Hello World!
This is another test
Hello World!

脚本定义了一个命令:print:将文本打印到STDOUT。

在脚本运行时,会一直等待来自STDIN的文本。如果输入一行文本并按下Enter键,则gawk会对这行文本执行一遍脚本。

和sed编辑器一样,gawk会对数据流中的每一行文本都执行脚本。

bash shell提供了Ctrl+D组合键来生成EOF(end-of-file)字符终止gawk程序,表明数据流已经结束。

使用该组合键可以终止gawk程序并返回到命令行界面。

8.1.2.3.使用数据字段变量

gawk处理文本文件中的数据时会自动为每一行的各个数据元素分配一个变量。

在默认情况下,gawk会将下列变量分配给文本行中的数据字段。

  • $0代表整个文本行。
  • $n(1~n)代表文本行中的第n个数据字段。

文本行中的数据字段通过字段分隔符来划分。

读取一行文本时,gawk会用预先定义好的字段分隔符划分出各个数据字段。默认是空白字符(比如空格或制表符)

使用$1字段变量来显示每行文本的第一个数据字段:

js 复制代码
$ cat data2.txt
One line of test text.
Two lines of test text.
Three lines of test text.
$ gawk '{print $1}' data2.txt
One
Two
Three

要读取的文件采用了其他的字段分隔符,可以通过-F选项指定.

将冒号指定为字段分隔符(-F:)来显示了系统中密码文件的第一个数据字段.

js 复制代码
$ gawk -F: '{print $1}' /etc/passwd
root
daemon
bin
...
christine
sshd

8.1.2.4.在脚本中使用多条命令

将多条命令组合成一个常规的脚本,在命令之间加入分号.

js 复制代码
$ echo "My name is Rich" | gawk '{$4="Christine"; print $0}'
My name is Christine

或使用次提示符

js 复制代码
$ gawk '{
> $4=" Christine "
> print $0 }'
My name is Rich
My name is Christine

与sed类似,未指定文件时,会从STDIN读取输入,使用Ctrl+D生成EOF来结束脚本.

8.1.2.5.从文件中读取脚本

跟sed编辑器一样,gawk允许将脚本保存在文件中,然后在命令行中引用脚本.

js 复制代码
$ cat script2.gawk
{ print $1 "'s home directory is " $6 }
$ gawk -F: -f script2.gawk /etc/passwd
root's home directory is /root
daemon's home directory is /usr/sbin
bin's home directory is /bin
...
sshd's home directory is /run/sshd

可以在脚本文件中指定多条命令。

js 复制代码
$ cat script3.gawk
{
text = "'s home directory is "
print $1 text $6
}
$ gawk -F: -f script3.gawk /etc/passwd

在gawk脚本中,引用变量值时无须使用 $ 符号。

8.1.2.6.在处理数据前运行脚本

gawk允许指定脚本何时运行。

默认情况gawk会从输入中读取一行文本,然后对数据执行脚本。有时候需要在处理数据前先运行脚本.

BEGIN关键字会强制gawk在读取数据前执行BEGIN关键字之后指定的脚本.

js 复制代码
$ gawk 'BEGIN {print "Hello World!"}'
Hello World!

BEGIN关键字在处理任何数据之前仅应用指定的脚本,在显示过文本后,脚本直接结束,不等待任何数据。

想使用正常的脚本来处理数据,则必须用另一个区域来定义脚本.

在gawk执行了BEGIN脚本后,会用第二段脚本来处理文件数据。

两段脚本仍会被视为gawk命令行中的一个文本字符串,所以需要加在一个单引号内.

js 复制代码
$gawk 'BEGIN {print "请每次输入一个单词!"}
> {print $1}'
请每次输入一个单词!
apple red
apple
old new
old
hello world
hello

8.1.2.7.在处理数据后运行脚本

和BEGIN关键字类似,END关键字允许指定一段脚本,gawk会在处理完数据后执行这段脚本

js 复制代码
$gawk 'BEGIN {print "请每次输入一个单词!"}
> {print $1}
> END {print "输入结束"}' data3.txt
请每次输入一个单词!
apple red
apple
old new
old
hello world
hello
输入结束

特殊变量FS是定义字段分隔符的另一种方法。无须依靠脚本用户通过命令行选项定义字段分隔符.

js 复制代码
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"
}
$ gawk -f script4.gawk /etc/passwd
The latest list of users and shells
UserID           Shell
--------         -------
root             /bin/bash
daemon           /usr/sbin/nologin
...
sshd             /usr/sbin/nologin
This concludes the listing

更多gawk进阶

8.2.sed编辑器基础命令

选项 描述
-e commands 处理输入时,加入额外的sed命令
-f file 处理输入时,将file中指定的命令添加到已有命令中
-n 不产生输出,使用p(print)命令完成输出

8.2.1.更多的替换选项

8.2.1.1.替换标志

替换命令在替换多行中的文本时使用,默认情况下它只替换每行中出现的第一处匹配文本。

js 复制代码
$ cat data4.txt
This is a test of the test script.
This is the second test of the test script.
$ sed 's/test/trial/' data4.txt
This is a trial of the test script.
This is the second trial of the test script.

要想替换每行中所有的匹配文本,必须使用替换标志(substitution flag)。替换标志在替换命令字符串之后设置。

js 复制代码
sed 's/pattern/replacement/flags' file

有4种可用的替换标志:

  • 数字,指明新文本将替换行中的第几处匹配。
  • g,指明新文本将替换行中所有的匹配。
  • p,指明打印出替换后的行。
  • w file,将替换的结果写入文件。

数字替换标志,替换指定匹配处:

js 复制代码
$ sed 's/test/trial/2' data4.txt
This is a test of the trial script.
This is the second test of the trial script.

g替换标志,替换所有:

js 复制代码
$ sed 's/test/trial/g' data4.txt
This is a trial of the trial script.
This is the second trial of the trial script.

p替换标志,打印出包含替换命令中指定匹配模式的文本行。通常和sed的-n选项配合使用.

-n选项会抑制sed编辑器的输出,替换标志p会输出替换后的行。配合使用只输出被替换命令修改过的行。

js 复制代码
$ cat data5.txt
This is a test line.
This is a different line.
$ sed -n 's/test/trial/p' data5.txt
This is a trial line.

w替换标志,将替换的结果(仅替换的行)输出保存到指定文件中.

sed编辑器的正常输出会被保存在STDOUT中。

js 复制代码
$ sed 's/test/trial/w test.txt' data5.txt
This is a trial line.
This is a different line.
$ cat test.txt
This is a trial line.

8.2.1.2.替换字符

在字符串中遇到不方便在替换模式中使用的字符。比如正斜线(/)替换文件中的路径会比较烦琐。

由于正斜线被用作替换命令的分隔符,因此它在匹配模式和替换文本中出现时,必须使用反斜线来转义。

如果想将/etc/passwd文件中的bash shell替换为C shell:

js 复制代码
$ sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd

为了解决这个问题,sed编辑器允许选择其他字符作为替换命令的替代分隔符:

js 复制代码
$ sed 's!/bin/bash!/bin/csh!' /etc/passwd

以上感叹号(!)被用作替换命令的分隔符.

8.2.2.使用地址

默认情况下,在sed编辑器中使用的命令会应用于所有的文本行。如果只想将命令应用于特定的某一行或某些行,可使用行寻址。

sed编辑器中有两种形式的行寻址。

  • 以数字形式表示的行区间。
  • 匹配行内文本的模式。

行寻址的格式:

js 复制代码
[address]command
# 将针对特定地址的多个命令分组
address {
    command1
    command2
    command3
}

sed编辑器会将指定的各个命令应用于匹配指定地址的文本行。

8.2.2.1.数字形式行寻址

在使用数字形式的行寻址时,可以用行号来引用文本流中的特定行。

sed编辑器会将文本流中的第一行编号为1,第n行编号为n.

在命令中指定的行地址既可以是单个行号,也可以是用起始行号、逗号以及结尾行号指定的行区间。

$可表示最后一行.

js 复制代码
$ cat data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$ sed '2s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$ sed '2,3s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy dog.
$ sed '2,$s/dog/cat/' data1.txt ##
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.
The quick brown fox jumps over the lazy cat.

8.2.2.2.使用文本模式过滤

sed编辑器允许指定文本模式来过滤出命令所应用的行.

必须将指定的模式(patten)放入正斜线内。sed编辑器会将该命令应用于包含匹配模式的行。

js 复制代码
sed '/pattern/command' file
js 复制代码
$ grep /bin/bash /etc/passwd
root:x:0:0:root:/root:/bin/bash
christine:x:1001:1001::/home/christine:/bin/bash
rich:x:1002:1002::/home/rich:/bin/bash
$ sed '/rich/s/bash/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
rich:x:1002:1002::/home/rich:/bin/csh

在文本模式中引入正则表达式来创建匹配效果更好的模式.

8.2.2.3.命令组

在单行中执行多条命令,可以用 {} 组合在一起,sed编辑器会执行匹配地址中列出的所有命令.

可以在一组命令前指定行区间.

js 复制代码
$ sed '2{
> s/fox/toad/
> s/dog/cat/
> }' data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown toad jumps over the lazy cat.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.

8.2.3.删除行(d)

文本替换命令并非sed编辑器唯一的命令。如果需要删除文本流中的特定行,可以使用删除(d)命令。

删除命令会删除匹配指定模式的所有行。使用该命令时如果忘记加入寻址模式,则流中的所有文本行都会被删除.

同样的,sed编辑器的删除命令也不会修改原始文件.

js 复制代码
$ cat data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog
$ sed 'd' data1.txt

从数据流中删除特定的文本行:

  • 通过行号指定:

    js 复制代码
    $ cat data6.txt
    This is line number 1.
    This is line number 2.
    This is the 3rd line.
    This is the 4th line.
    $ sed '3d' data6.txt
    This is line number 1.
    This is line number 2.
    This is the 4th line.
  • 通过特定行区间指定:

    js 复制代码
    $ sed '2,3d' data6.txt
    This is line number 1.
    This is the 4th line.
  • 特殊的末行字符指定:

    js 复制代码
    $ sed '3,$d' data6.txt
    This is line number 1.
    This is line number 2.
  • 模式匹配:

    js 复制代码
    $ sed '/number 1/d' data6.txt
    This is line number 2.
    This is the 3rd line.
    This is the 4th line.
  • 使用两个文本模式来删除某个区间内的行:
    一个模式会"启用"行删除功能,第二个模式会"关闭"行删除功能,sed编辑器会删除包含两个指定行与之间的所有行.
    只要sed编辑器在数据流中匹配到了开始模式,就会启用删除功能.第二个包含开始模式的行也会触发删除命令,未找到结束模式,则剩余的行会被全部删除.

js 复制代码
$ cat data7.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
This is line number 1 again; we want to keep it.
This is more text we want to keep.
Last line in the file; we want to keep it.
$ sed '/1/,/3/d' data7.txt
This is the 4th line.

8.2.4.插入和附加文本(a\i)

sed编辑器也可以向数据流中插入和附加文本行。

  • 插入(insert)(i)命令会在指定行前增加一行。
  • 附加(append)(a)命令会在指定行后增加一行。

命令不能在单个命令行中使用。必须指定 插入还是附加 到另一行.

js 复制代码
sed '[address]command\
new line' file

插入与附加

js 复制代码
$ echo "Test Line 2" | sed 'i\Test Line 1'
Test Line 1
Test Line 2
$ echo "Test Line 2" | sed 'a\Test Line 1'
Test Line 2
Test Line 1
$ echo "Test Line 2" | sed 'i\
> Test Line 1'
Test Line 1
Test Line 2

向数据流内部插入或附加数据,须用地址指定数据出现在什么位置。

只能指定一个行地址。不能用行区间.(只能将文本插入或附加到某一行而不是行区间的前后)

js 复制代码
$ cat data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
$ sed '3i\
> This is an inserted line.
> ' data6.txt
This is line number 1.
This is line number 2.
This is an inserted line.
This is the 3rd line.
This is the 4th line.
$
$ sed '$a\
> This line was added to the end of the file.
> ' data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
This line was added to the end of the file.

在数据流的起始位置增加一个新行。只要在第一行之前插入新行。

在数据流的末尾位置增加一个新行。只要在最后一行之后附加新行。

添加多行

要插入或附加多行文本,必须在要插入或附加的每行新文本末尾使用反斜线(\):

js 复制代码
$ sed '1i\
> This is an inserted line.\
> This is another inserted line.
> ' data6.txt
This is an inserted line.
This is another inserted line.
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.

8.2.5.修改行©

修改(c)命令允许修改数据流中整行文本的内容。必须在sed命令中单独指定一行.

js 复制代码
$ sed '2c\
> This is a changed line of text.
> ' data6.txt
This is line number 1.
This is a changed line of text.
This is the 3rd line.
This is the 4th line.
$ sed '/3rd line/c\
> This is a changed line of text.
> ' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is the 4th line.

文本模式修改命令会修改所匹配到的任意文本行.

在修改命令中使用地址区间,会将区间内的所有内容替换为一个文本内容,而不会将每一行替换一次.

js 复制代码
$ cat data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
$ sed '2,3c\
> This is a changed line of text.
> ' data6.txt
This is line number 1.
This is a changed line of text.
This is the 4th line.

8.2.6.转换命令(y)

转换(y)命令是唯一可以处理单个字符的sed编辑器命令。

js 复制代码
sed '[address]y/inchars/outchars/' file

转换命令会对inchars和outchars的字符进行一对一的映射。

inchars中的第一个字符会被转换为outchars中的第一个字符,inchars中的第n字符会被转换成outchars中的第n字符。

如果inchars和outchars的长度不同,sed编辑器会产生错误消息。

转换命令是一个全局命令,会对文本行中匹配到的所有指定字符进行转换,不考虑字符出现的位置,也无法对特定位置字符的转换进行限制:

js 复制代码
$ cat data9.txt
This is line 1.
This is line 5.
This is line 1 again.
This is line 3 again.
This is the last file line.
$ sed 'y/123/789/' data9.txt
This is line 7.
This is line 5.
This is line 7 again.
This is line 9 again.
This is the last file line.
$ echo "Test #1 of try #1." | sed 'y/123/678/'
Test #6 of try #6.

8.2.7.打印

打印数据流中的信息。

  • 打印(p)命令用于打印文本行。
  • 等号(=)命令用于打印行号。
  • 列出(l)命令用于列出行。

打印行§

和替换命令中的p标志类似,打印命令用于打印sed编辑器输出中的一行。

js 复制代码
$ echo "this is a test" | sed 'p'
this is a test
this is a test

常见的用法是打印包含匹配文本模式的行,通过-n抑制其他行输出:

js 复制代码
$ cat data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
$ sed -n '/3rd line/p' data6.txt
This is the 3rd line.

在使用替换或修改命令做出改动之前查看相应的行:

js 复制代码
$ sed -n '/3/{
> p
> s/line/test/p
> }' data6.txt
This is the 3rd line.
This is the 3rd test.

打印数据流中的部分行:

js 复制代码
$ sed -n '2,3p' data6.txt
This is line number 2.
This is the 3rd line.

打印行号(=)

=等号命令会打印文本行在数据流中的行号。行号由数据流中的换行符决定。

sed编辑器在实际文本行之前会先打印行号。

js 复制代码
$ cat data1.txt
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$
$ sed '=' data1.txt
1
The quick brown fox jumps over the lazy dog.
2
The quick brown fox jumps over the lazy dog.
3
The quick brown fox jumps over the lazy dog.
4
The quick brown fox jumps over the lazy dog.

让sed编辑器只显示包含匹配文本模式的文本行的行号和内容:

js 复制代码
$ cat data7.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
This is line number 1 again; we want to keep it.
This is more text we want to keep.
Last line in the file; we want to keep it.
$ sed -n '/text/{
> =
> p
> }' data7.txt
6
This is more text we want to keep.

列出行(l)

列出命令可以打印数据流中的文本和不可打印字符。

在显示不可打印字符的时候,可以使用反斜杠加八进制值,或使用标准的C语言命名规范,比如\t用于代表制表符.

js 复制代码
$ cat data10.txt
This    line    contains        tabs.
This line does contain tabs.
$ sed -n 'l' data10.txt
This\tline\tcontains\ttabs.$
This line does contain tabs.$

8.2.8.处理文件

写入文件(w)

命令格式:

js 复制代码
sed '[address]w filename' file

filename可以使用相对路径或绝对路径.用户必须有文件的写权限。地址可以是任意类型的寻址方式.

js 复制代码
$ sed '1,2w test.txt' data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
$ cat test.txt
This is line number 1.
This is line number 2.

可以使用-n选项抑制输出.

根据一些文本值,从主文件(比如下面的邮件列表)中创建一份数据文件,使用写入命令会非常方便:

js 复制代码
$ cat data12.txt
Blum, R       Browncoat
McGuiness, A  Alliance
Bresnahan, C  Browncoat
Harken, C     Alliance
$ sed -n '/Browncoat/w Browncoats.txt' data12.txt
$ cat Browncoats.txt
Blum, R       Browncoat
Bresnahan, C  Browncoat

读取数据®

取(r)命令允许将一条独立文件中的数据插入 数据流。将文件内容插入指定地址之后.

无法使用地址区间,只能指定单个行号或文本模式地址。

命令格式:

js 复制代码
sed '[address]r filename' file
js 复制代码
$ cat data13.txt
This is an added line.
This is a second added line.
$ sed '3r data13.txt' data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is an added line.
This is a second added line.
This is the 4th line.
$ sed '/number 2/r data13.txt' data6.txt
This is line number 1.
This is line number 2.
This is an added line.
This is a second added line.
This is the 3rd line.
This is the 4th line.
$ sed '$r data13.txt' data6.txt
This is line number 1.
This is line number 2.
This is the 3rd line.
This is the 4th line.
This is an added line.
This is a second added line.

读取命令和删除命令配合使用,利用一个文件中的数据来替换另一个文件中的占位文本。

假如你保存在文本文件中的套用信件如下:

js 复制代码
$ cat notice.std
Would the following people:
LIST
please report to the ship's captain.

在占位文本后插入名单,只需使用读取命令即可。但这样的话,占位文本仍然会留在输出中。为此,可以用删除命令删除占位文本

js 复制代码
$ sed '/LIST/{
> r data12.txt
> d
> }' notice.std
Would the following people:
Blum, R       Browncoat
McGuiness, A  Alliance
Bresnahan, C  Browncoat
Harken, C     Alliance
please report to the ship's captain.

文件夹下文件

-s选项可以告知sed将目录内的各个文件作为单独的流

js 复制代码
$ sed -sn '1s!/bin/sh!/bin/bash!' OldScripts/*.sh

将 OldScripts文件夹下的.sh文件第一行内的/bin/sh的替换为/bin/bash.

相关推荐
Mortal_hhh8 分钟前
VScode的C/C++点击转到定义,不是跳转定义而是跳转声明怎么办?(内附详细做法)
ide·vscode·stm32·编辑器
€☞扫地僧☜€1 小时前
docker 拉取MySQL8.0镜像以及安装
运维·数据库·docker·容器
hjjdebug1 小时前
linux 下 signal() 函数的用法,信号类型在哪里定义的?
linux·signal
其乐无涯1 小时前
服务器技术(一)--Linux基础入门
linux·运维·服务器
Diamond技术流1 小时前
从0开始学习Linux——网络配置
linux·运维·网络·学习·安全·centos
写bug的小屁孩1 小时前
前后端交互接口(三)
运维·服务器·数据库·windows·用户界面·qt6.3
斑布斑布1 小时前
【linux学习2】linux基本命令行操作总结
linux·运维·服务器·学习
紅色彼岸花1 小时前
第六章:DNS域名解析服务器
运维·服务器
Spring_java_gg1 小时前
如何抵御 Linux 服务器黑客威胁和攻击
linux·服务器·网络·安全·web安全
✿ ༺ ོIT技术༻1 小时前
Linux:认识文件系统
linux·运维·服务器