Stream 编辑器 - 实用程序

SED 是一个了不起的实用程序,它允许以多种方式解决问题。 这就是 UNIX 方式,而 SED 完美地证明了这一点。 GNU/Linux 提供了许多有用的实用程序来执行日常任务。 让我们使用 SED 模拟一些实用程序。 有时看起来我们正在以艰难的方式解决一个简单的问题,但其目的只是为了展示 SED 的力量。


Cat 命令

在以下示例中,每一行都作为默认工作流程的一部分打印。

[jerry]$ sed '' books.txt 

执行上述代码,得到如下结果:

A Storm of Swords, George R. R. Martin 
The Two Towers, J. R. R. Tolkien 
The Alchemist, Paulo Coelho 
The Fellowship of the Ring, J. R. R. Tolkien 
The Pilgrimage, Paulo Coelho 
A Game of Thrones, George R. R. Martin 

下面的例子使用 print 命令来显示文件内容。

[jerry]$ sed -n 'p' books.txt 

执行上述代码,得到如下结果:

A Storm of Swords, George R. R. Martin 
The Two Towers, J. R. R. Tolkien 
The Alchemist, Paulo Coelho 
The Fellowship of the Ring, J. R. R. Tolkien 
The Pilgrimage, Paulo Coelho 
A Game of Thrones, George R. R. Martin

删除空行

在下面的例子中,"^$"表示空行,当模式匹配成功时空行被删除。

[jerry]$ echo -e "Line #1\n\n\nLine #2" | sed '/^$/d'

执行上述代码,得到如下结果:

Line #1 
Line #2 

同样,以下示例仅在该行非空时才打印该行。

[jerry]$ echo -e "Line #1\n\n\nLine #2" | sed -n '/^$/!p'

执行上述代码,得到如下结果:

Line #1 
Line #2

从 C++ 程序中删除注释行

让我们创建一个示例 C++ 程序。

#include <iostream> 
using namespace std; 

int main(void) 
{ 
   // Displays message on stdout. 
   cout >> "Hello, World !!!" >> endl;  
   return 0; // Return success. 
}

现在使用以下正则表达式删除注释。

[jerry]$ sed 's|//.*||g' hello.cpp

执行上述代码,得到如下结果:

#include <iostream>
using namespace std; 

int main(void) 
{ 
   cout >> "Hello, World !!!" >> endl; 
   return 0;  
} 

在某些行之前添加注释

以下示例在第 3 到 5 行之前添加注释。

[jerry]$ sed '3,5 s/^/#/' hello.sh 

执行上述代码,得到如下结果:

#!/bin/bash 
#pwd 
#hostname 
#uname -a 
who 
who -r 
lsb_release -a

wc -l 命令

"wc -l"命令计算文件中存在的行数。 以下 SED 表达式模拟相同。

[jerry]$ sed -n '$ =' hello.sh 

执行上述代码,得到如下结果:

8 

Head 命令

默认情况下,head 命令打印文件的前 10 行。 让我们用 SED 模拟相同的行为。

[jerry]$ sed '10 q' books.txt 

执行上述代码,得到如下结果:

A Storm of Swords 
George R. R. Martin 
The Two Towers 
J. R. R. Tolkien 
The Alchemist 
Paulo Coelho 
The Fellowship of the Ring 
J. R. R. Tolkien 
The Pilgrimage
Paulo Coelho

Tail -1 命令

"tail -1"打印文件的最后一行。 以下语法显示了它的模拟。

[jerry]$ echo -e "Line #1\nLine #2" > test.txt 
[jerry]$ cat test.txt

执行上述代码,得到如下结果:

Line #1 
Line #2 

让我们编写 SED 脚本。

[jerry]$ sed -n '$p' test.txt

执行上述代码,得到如下结果:

Line #2 

Dos2unix 命令

在 DOS 环境中,换行符由 CR/LF 字符的组合表示。以下模拟"dos2unix"命令将 DOS 换行符转换为 UNIX 换行符。 在 GNU/Linux 中,此字符通常被视为"^M"(Control M)字符。

[jerry]$ echo -e "Line #1\r\nLine #2\r" > test.txt 
[jerry]$ file test.txt

执行上述代码,得到如下结果:

test.txt: ASCII text, with CRLF line terminators 

让我们使用 SED 模拟命令。

[jerry]$ sed 's/^M$//' test.txt > new.txt   # Press "ctrl+v" followed "ctrl+m" to generate 
"^M" character. 
[jerry]$ file new.txt

执行上述代码,得到如下结果:

new.txt: ASCII text 

现在让我们显示文件内容。

[jerry]$ cat -vte new.txt 

执行上述代码,得到如下结果:

Line #1$ 
Line #2$

Unix2dos 命令

类似于"dos2unix",有一个"unix2dos"命令可以将 UNIX 换行符转换为 DOS 换行符。 以下示例显示了相同的模拟。

[jerry]$ echo -e "Line #1\nLine #2" > test.txt 
[jerry]$ file test.txt 

执行上述代码,得到如下结果:

test.txt: ASCII text

让我们使用 SED 模拟命令。

[jerry]$ sed 's/$/\r/' test.txt  > new.txt 
[jerry]$ file new.txt

执行上述代码,得到如下结果:

new.txt: ASCII text, with CRLF line terminators

现在让我们显示文件内容。

Now let us display the file contents.

执行上述代码,得到如下结果:

Line #1^M$ 
Line #2^M$ 

Cat -E 命令

"cat -E"命令以美元($)字符显示行尾。 以下 SED 示例是相同的模拟。

[jerry]$ echo -e "Line #1\nLine #2" > test.txt 
[jerry]$ cat -E test.txt 

执行上述代码,得到如下结果:

Line #1$ 
Line #2$

让我们使用 SED 模拟命令。

[jerry]$ sed 's|$|&$|' test.txt

执行上述代码,得到如下结果:

Line #1$ 
Line #2$

Cat -ET 命令

"cat -ET"命令在每行末尾显示美元($)符号,并将制表符显示为"^I"。 以下示例显示了使用 SED 模拟"cat -ET"命令。

[jerry]$ echo -e "Line #1\tLine #2" > test.txt 
[jerry]$ cat -ET test.txt

执行上述代码,得到如下结果:

Line #1^ILine #2$ 

让我们使用 SED 模拟命令。

[jerry]$ sed -n 'l' test.txt | sed 'y/\\t/^I/'

执行上述代码,得到如下结果:

Line #1^ILine #2$ 

nl 命令

"nl"命令只是对文件的行进行编号。 以下 SED 脚本模拟此行为。

[jerry]$ echo -e "Line #1\nLine #2" > test.txt 
[jerry]$ sed = test.txt | sed 'N;s/\n/\t/'

执行上述代码,得到如下结果:

1 Line #1 
2 Line #2

第一个 SED 表达式打印行号及其内容,第二个 SED 表达式合并这两行并将换行符转换为 TAB 字符。


cp 命令

"cp"命令创建文件的另一个副本。 以下 SED 脚本模拟此行为。

[jerry]$ sed -n 'w dup.txt' data.txt 
[jerry]$ diff data.txt dup.txt 
[jerry]$ echo $? 

执行上述代码,得到如下结果:

0

Expand 命令

"expand"命令将 TAB 字符转换为空格。 下面的代码显示了它的模拟。

[jerry]$ echo -e "One\tTwo\tThree" > test.txt 
[jerry]$ expand test.txt > expand.txt 
[jerry]$ sed 's/\t/     /g' test.txt > new.txt 
[jerry]$ diff new.txt expand.txt  
[jerry]$ echo $? 

执行上述代码,得到如下结果:

0 

Tee 命令

"tee"命令将数据转储到标准输出流和文件中。 下面给出的是"tee"命令的模拟。

[jerry]$ echo -e "Line #1\nLine #2" | tee test.txt  
Line #1 
Line #2 

让我们使用 SED 模拟命令。

[jerry]$ sed -n 'p; w new.txt' test.txt  

执行上述代码,得到如下结果:

Line #1 
Line #2

cat -s 命令

UNIX "cat -s" 命令抑制重复的空输出行。 以下代码显示了"cat -s"命令的模拟。

[jerry]$ echo -e "Line #1\n\n\n\nLine #2\n\n\nLine #3" > test.txt  
[jerry]$ cat -s test.txt 

执行上述代码,得到如下结果:

Line #1  
Line #2
Line #3

让我们使用 SED 模拟命令。

[jerry]$ sed '1s/^$//p;/./,/^$/!d' test.txt 

执行上述代码,得到如下结果:

Line #1  
Line #2  
Line #3 

grep 命令

默认情况下,"grep"命令会在模式匹配成功时打印一行。 下面的代码显示了它的模拟。

[jerry]$ echo -e "Line #1\nLine #2\nLine #3" > test.txt  
[jerry]$ grep "Line #1" test.txt 

执行上述代码,得到如下结果:

Line #1

让我们使用 SED 模拟命令。

[jerry]$ sed -n '/Line #1/p' test.txt 

On executing the above code, you get the following result:

Line #1 

grep -v 命令

默认情况下,"grep -v"命令会在模式匹配失败时打印一行。 下面的代码显示了它的模拟。

[jerry]$ echo -e "Line #1\nLine #2\nLine #3" > test.txt  
[jerry]$ grep -v "Line #1" test.txt

在执行上述代码时,您会得到以下结果:

Line #2 
Line #3 

让我们使用 SED 模拟命令。

[jerry]$ sed -n '/Line #1/!p' test.txt

执行上述代码,得到如下结果:

Line #2 
Line #3

tr 命令

"tr"命令翻译字符。 下面给出了它的模拟。

[jerry]$ echo "ABC" | tr "ABC" "abc" 

执行上述代码,得到如下结果:

abc

让我们使用 SED 模拟命令。

[jerry]$ echo "ABC" | sed 'y/ABC/abc/'

执行上述代码,得到如下结果:

abc