sed 编辑器提供了 3 个可用于处理多行文本的特殊命令:
next 命令
单行 next 命令
$ cat data1.txt
Header Line
Data Line #1
End of Data Lines
$
$ sed '/Header/{n ; d}' data1.txt
Header Line
Data Line #1
End of Data Lines
$
合并文本行
$ cat data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed '/First/{ N ; s/\n/ / }' data2.txt
Header Line
First Data Line Second Data Line
End of Data Lines
$
$ cat data3.txt
On Tuesday, the Linux System
Admin group meeting will be held.
All System Admins should attend.
Thank you for your cooperation.
$
$ sed 's/System Admin/DevOps Engineer/' data3.txt
On Tuesday, the Linux System
Admin group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.
$
$ sed 'N ; s/System.Admin/DevOps Engineer/' data3.txt
On Tuesday, the Linux DevOps Engineer group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.
$
$ sed 'N
> s/System\nAdmin/DevOps\nEngineer/
> s/System Admin/DevOps Engineer/
> ' data3.txt
On Tuesday, the Linux DevOps
Engineer group meeting will be held.
All DevOps Engineers should attend.
Thank you for your cooperation.
$
$ sed '
> s/System Admin/DevOps Engineer/
> N
> s/System\nAdmin/DevOps\nEngineer/
> ' data4.txt
$ sed 'N ; /System\nAdmin/d' data4.txt
All System Admins should attend.
$
$ sed 'N ; /System\nAdmin/D' data4.txt
Admin group meeting will be held.
All System Admins should attend.
$
$ cat data5.txt
Header Line
First Data Line
End of Data Lines
$
$ sed '/^$/{N ; /Header/D}' data5.txt
Header Line
First Data Line
End of Data Lines
$
$ sed -n 'N ; /System\nAdmin/P' data3.txt
On Tuesday, the Linux System
$
$ cat corruptData.txt
Header Line#
@
Data Line #1
Data Line #2#
@
End of Data Lines#
@
$
$ sed -n '
> N
> s/#\n@//
> P
> D
> ' corruptData.txt
Header Line
Data Line #1
Data Line #2
End of Data Lines
$
模式空间(pattern space )是一块活跃的缓冲区,在 sed 编辑器执行命令时保存着待检查的文本,但它并不是 sed 编辑器保存文本的唯一空间。
sed 编辑器还有另一块称作保留空间(hold space)的缓冲区。当你在处理模式空间中的某些行时,可以用保留空间临时保存部分行。
与保留空间相关的命令有 5 个,sed 编辑器的保留空间命令如下表:
命令 | 描述 |
---|---|
h | 将模式空间复制到保留空间 |
H | 将模式空间附加到保留空间 |
g | 将保留空间复制到模式空间 |
G | 将保留空间附加到模式空间 |
x | 交换模式空间和保留空间的内容 |
这些命令可以将文本从模式空间复制到保留空间,以便清空模式空间,载入其他要处理的字符串。
通常, 在使用 h 命令或 H 命令将字符串移入保留空间后,最终还是要用 g 命令、 G 命令或 x 命令将保存的字符串移回模式空间(否则,一开始就不用考虑保存的问题)。
例子,如何用 h 命令和 g 命令在缓冲空间之间移动数据:
$ cat data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed -n '/First/ {
> h ; p ;
> n ; p ;
> g ; p }
> ' data2.txt
First Data Line
Second Data Line
First Data Line
$
通过保留空间来回移动文本行,可以强制 First Data Line 输出在 Second Data Line
之后。如果去掉第一个 p 命令,则可以将这两行以相反的顺序输出:
$ sed -n '/First/ {
> h ;
> n ; p
> g ; p }
> ' data2.txt
Second Data Line
First Data Line
$
$ sed -n '/Header/!p' data2.txt
First Data Line
Second Data Line
End of Data Lines
$
$ cat data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed -n '{1!G ; h ; $p }' data2.txt
End of Data Lines
Second Data Line
First Data Line
Header Line
$
sed 编辑器还提供了一种方法,这种方法可以基于地址、地址模式或地址区间排除一整段命令。这允许你只对数据流中的特定行执行部分命令。
分支(b)命令的格式如下:
[address]b [label]
下面这个例子使用了分支命令的 address 参数,但未指定 label:
$ cat data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed '{2,3b ;
> s/Line/Replacement/}
> ' data2.txt
Header Replacement
First Data Line
Second Data Line
End of Data Replacements
$
如果不想跳到脚本末尾,可以定义 label 参数,指定分支命令要跳转到的位置。标签以冒号开始,最多可以有 7 个字符:
:label2
$ sed '{/First/b jump1 ;
> s/Line/Replacement/
> :jump1
> s/Line/Jump Replacement/}
> ' data2.txt
Header Replacement
First Data Jump Replacement
Second Data Replacement
End of Data Replacements
$
也可以跳转到靠前的标签,达到循环的效果:
$ echo "This, is, a, test, to, remove, commas." |
> sed -n {'
> :start
> s/,//1p
> /,/b start
> }'
[address]t [label]
$ sed '{s/First/Matched/ ; t
> s/Line/Replacement/}
> ' data2.txt
Header Replacement
Matched Data Line
Second Data Replacement
End of Data Replacements
$
$ echo "The cat sleeps in his hat." |
> sed 's/.at/"&"/g'
The "cat" sleeps in his "hat".
$
$ echo "The Guide to Programming" |
> sed '
> s/\(Guide to\) Programming/\1 DevOps/'
The Guide to DevOps
$
$ echo "That furry cat is pretty." |
> sed 's/furry \(.at\)/\1/'
That cat is pretty.
$
$ echo "That furry hat is pretty." |
> sed 's/furry \(.at\)/\1/'
That hat is pretty.
$
$ echo "1234567" | sed '{
> :start
> s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/
> t start}'
1,234,567
$
.*[0-9]
[0-9]{3}
$ cat reverse.sh
#!/bin/bash
# Shell wrapper for sed editor script
# to reverse test file lines.
#
sed -n '{1!G; h; $p}' $1
#
exit
$
$ ./reverse.sh data2.txt
$ cat fact.sh
#!/bin/bash
# Shell wrapper for sed editor script
# to calculate a factorial, and
# format the result with commas.
#
factorial=1
counter=1
number=$1
#
while [ $counter -le $number ]
do
factorial=$[ $factorial * $counter ]
counter=$[ $counter + 1 ]
done
#
result=$(echo $factorial |
sed '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/
t start
}')
#
echo "The result is $result"
#
exit
$
$ ./fact.sh 20
The result is 2,432,902,008,176,640,000
$
$ sed 'G' data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
$ sed '$!G' data2.txt
Header Line
First Data Line
Second Data Line
End of Data Lines
$
/^$/d
$ sed '/^$/d ; $!G' data6.txt
Line one.
Line two.
Line three.
Line four.
$
$ sed '=' data2.txt | sed 'N; s/\n/ /'
1 Header Line
2 First Data Line
3 Second Data Line
4 End of Data Lines
$
$ sed -n '$p' data2.txt
End of Data Lines
$
$ cat data7.txt
Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line1
Line2
Line3
Line4
Line5
Line6
Line7
Line8
Line9
Line10
Line11
Line12
Line13
Line14
Line15
$
$ sed '{
> :start
> $q ; N ; 11,$D
> b start
> }' data7.txt
Line6
Line7
Line8
Line9
Line10
Line11
Line12
Line13
Line14
Line15
$
删除连续的空行
$ sed '/./,/^$/!d' data8.txt
删除开头的空行
$ sed '/./,$!d' data9.txt
删除结尾的空行
$ sed '{
> :start
> /^\n*$/{$d; N; b start}
> }' data10.txt
$ sed 's/<[^>]*>//g' data11.txt
$ sed 's/<[^>]*>//g ; /^$/d' data11.txt