Linux应用之sed删除空行

一、sed编辑器介绍

sed编辑器被称作流编辑器(stream editor),和普通的交互式文本编辑器恰好相反。在交互式文本编辑器中(比如vim),你可以用键盘命令来交互式插入、删除或替换数据中的文本。流编辑器则会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。
sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中(即脚本文件)。sed编辑器会执行下列操作:

  • 依次从输入中读取一行数据
  • 根据所提供的编辑器命令匹配数据
  • 按照命令修改流中的数据
  • 将新的输数据输出到STDOUT

在流编辑器将所有命令与一行数据匹配完毕后,它会读取下一行数据并重复这个过程,直至处理完所有数据后终止。
sed命令的格式如下

sed options script file

二、sed删除空白行

说明:在使用之前假设读者有基本的正则知识,如果没有,请自行学习

1. 删除连续的空白行

如果我们的文本各行之间有不定数量的空白行,阅读起来颇有些费力,且不美观,我们希望各行之间间隔是固定的,比如仅有一行空白行的间隔,我们可以用到下面脚本:

/./ , /^$/!d

区间/./到/^$/的开始抵制会匹配任何含有至少一个字符的行,区间的结束地址会匹配一个空行,在这个区间的行不会被删除。
实例

~$ cat example1
Such stories set us thinking, 

wondering what we should do under similar circumstances. 


What events, what experiences, 

what associations should we crowd into those last hours as mortal beings, 


what regrets?
~$ sed '/./,/^$/!d' example1
Such stories set us thinking, 

wondering what we should do under similar circumstances. 

What events, what experiences, 

what associations should we crowd into those last hours as mortal beings, 

what regrets?
~$

原来不规则的空白行变得均匀了。该示例中最后一行之后无内容,如果最后一行文字之后还有空白行,处理之后一会显示一行空白行。

2. 删除开头的空白行

如果一段文本中开头有多行空白,显然会给阅读带来不便。删除开头的空白行与上面思路比较相似,我们可以用到下面脚本:

/./ , $!d

这个脚本将会对从有字符的行开始,一直到结束,这样一个区间的内容都不会被删除,也就是第一行正式内容之前的空白都会被删除。
实例

~$ cat example2



Such stories set us thinking, 

wondering what we should do under similar circumstances. 
What events, what experiences, 
what associations should we crowd into those last hours as mortal beings, 
what regrets?
~$ sed '/./, $!d' example2
Such stories set us thinking, 

wondering what we should do under similar circumstances. 
What events, what experiences, 
what associations should we crowd into those last hours as mortal beings, 
what regrets?
~$

3. 删除结尾的空白行

删除连续的空白行中我们提到,对最后一行的处理也会包含一行空白行,也许这并不是我们想要的结果,我们希望最后一行不含空白行,我们可以用到下面脚本:

sed ‘{
:start
/^\n*$/{$d; N; b start}
}’

这段脚本可能稍微显得有些复杂,在正常脚本的花括号中还有花括号,这允许你在整个命令脚本中将一些命令分组,该分组命令会被应用到指定的地址上。这里用到了分支标签b,可以实现跳转,就像C语言中的循环。其含义就是如果找到了一行它仅有一个换行符,而且还是最后一行,那么就删除它,否则会继续往后匹配。
实例

~$ cat example3
Such stories set us thinking, 

wondering what we should do under similar circumstances. 

What events, what experiences, 
what associations should we crowd into those last hours as mortal beings, 
what regrets?

~$ sed '{
:start
/^\n*$/{$d; N; b start}
}' example3
Such stories set us thinking, 

wondering what we should do under similar circumstances. 

What events, what experiences, 
what associations should we crowd into those last hours as mortal beings, 
what regrets?
~$

4. 删除HTML标签

应用中我们不少会从命令行去get一些网页信息,其中包含了大量的html标签信息,不利于我们获取其中的主要信息,我们需要将其格式化为普通文本,我们可以用到下面脚本:

s/ < [^>]*>//g ; /^$/d
**实例**
~$ cat example4
<html>
<head>
<title>This is the page</title>
</head>
<body>
<p>
This is the first line in the web page
This should provide some useful
information to use in our sed script
</p>
</body>
</html>
~$ sed -e 's/<[^>]*>//g ; /^$/d' data.txt
This is the page
This is the first line in the web page
This should provide some useful
information to use in our sed script
~$

说明:example4中的内容每一行之后立即换行,不含任何空格或者tab,读者可以尝试,在一些标签后面加一些空格或者tab,得到的内容将会不一样。

我们留心会发现,这里的所有内容都是五缩进的,然而我们标准的html结构中通常是包含各种缩进关系的,比如下面的例子

~$ cat example5
<html>
	<head>
		<title>This is the page</title>
	</head>
		<body>
		<p>
		This is the first line in the web page
		This should provide some useful
		information to use in our sed script
		</p>
	</body>
</html>
~$ sed -e 's/<[^>]*>//g ; /^$/d' example5
	
		This is the page
	
		
		
		This is the first line in the web page
		This should provide some useful
		information to use in our sed script
		
	
~$

标签都删掉了,但是空行却任然存在,为什么?我们将上述输出保存,然后使用cat -t看看里面的具体内容:

~$ sed -e 's/<[^>]*>//g ; /^$/d' data.txt > test
~$ cat -t test 
^I
^I^IThis is the page
^I
^I^I
^I^I
^I^IThis is the first line in the web page
^I^IThis should provide some useful
^I^Iinformation to use in our sed script
^I^I
^I
~$

可以看到,文本中的每个空行是实际上都有一个不可打印字符^I,它表示一个TAB,他在执行正则匹配/^$/d时 ,二则并不匹配,所以删除空行操作并未执行。所以需要对该规则进行修改:

s/ < [^>]*>//g ; /^ [[:space:]]*$/d
区别在于空白行匹配中间增加了[[:space]]*,[[:space]]表示任意空白字符,包括空格、制表符、NL、FF、VT和CR。执行效果如下:
~$ sed -e 's/<[^>]*>//g ; /^[[:space:]]*$/d' example5
		This is the page
		This is the first line in the web page
		This should provide some useful
		information to use in our sed script
~$

可以看到,空行都删除完了,但是每行之间任然有一部分空白,我们可以在上面的基础上再次处理从而是删掉该部分空白,修改规则如下

s/ < [^>]*>//g ; /^ [[:space:]]*$/d ; s/^[[:space:]]*$//g
我们对每一行开始的空格或者TAB进行匹配替换,从而达到删除的效果:
~$ sed -e 's/<[^>]*>//g ; /^[[:space:]]*$/d; s/^[[:space:]]*//g' example5
This is the page
This is the first line in the web page
This should provide some useful
information to use in our sed script
~$

现在效果好多了,你可以将输出重定向到你指定的文件中去。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章