替代命令
诸如“查找和替换”之类的文本替换操作在任何文本编辑器中都很常见。在本节中,我们将说明 SED 如何执行文本替换。下面给出了替换命令的语法。
[address1[,address2]]s/pattern/replacement/[flags]
这里,address1和address2分别是开始和结束地址,可以是行号或模式字符串。这两个地址都是可选参数。模式是我们想要用替换字符串替换的文本。此外,我们可以使用 SED 指定可选标志。
在books.txt 文件中,我们使用逗号(,) 分隔每一列。让我们使用竖线(|)来分隔每一列。为此,请将逗号 (,) 替换为竖线 (|)。
[jerry]$ sed 's/,/ | /' books.txt
执行上面的代码,你会得到以下结果:
1) A Storm of Swords | George R. R. Martin, 1216
2) The Two Towers | J. R. R. Tolkien, 352
3) The Alchemist | Paulo Coelho, 197
4) The Fellowship of the Ring | J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho, 288
6) A Game of Thrones | George R. R. Martin, 864
如果你仔细观察,只有第一个逗号被替换,第二个保持原样。为什么?一旦模式匹配,SED 就会用替换字符串替换它并移动到下一行。默认情况下,它只替换第一次出现。要替换所有匹配项,请使用带有 SED 的全局标志 (g),如下所示:
[jerry]$ sed 's/,/ | /g' books.txt
执行上面的代码,你会得到以下结果:
1) A Storm of Swords | George R. R. Martin | 1216
2) The Two Towers | J. R. R. Tolkien | 352
3) The Alchemist | Paulo Coelho | 197
4) The Fellowship of the Ring | J. R. R. Tolkien | 432
5) The Pilgrimage | Paulo Coelho | 288
6) A Game of Thrones | George R. R. Martin | 864
现在所有出现的逗号(,)都替换为竖线(|)。
我们可以指示 SED 仅在模式匹配成功时执行文本替换。以下示例仅当一行包含模式 The Pilgrimage 时才将逗号 (,) 替换为竖线 (|)。
[jerry]$ sed '/The Pilgrimage/ s/,/ | /g' books.txt
执行上面的代码,你会得到以下结果:
1) A Storm of Swords, George R. R. Martin, 1216
2) The Two Towers, J. R. R. Tolkien, 352
3) The Alchemist, Paulo Coelho, 197
4) The Fellowship of the Ring, J. R. R. Tolkien, 432
5) The Pilgrimage | Paulo Coelho | 288
6) A Game of Thrones, George R. R. Martin, 864
除此之外,SED 可以替换特定出现的模式。让我们只用竖线(|)替换逗号(,)的第二个实例。
[jerry]$ sed 's/,/ | /2' books.txt
执行上面的代码,你会得到以下结果:
1) A Storm of Swords, George R. R. Martin | 1216
2) The Two Towers, J. R. R. Tolkien | 352
3) The Alchemist, Paulo Coelho | 197
4) The Fellowship of the Ring, J. R. R. Tolkien | 432
5) The Pilgrimage,Paulo Coelho | 288
6) A Game of Thrones, George R. R. Martin | 864
在上面的示例中,SED 命令末尾(或标志位置)的数字表示第二次出现。
SED 提供了一个有趣的功能。执行替换后,SED 提供了一个选项来仅显示更改的行。为此,SED 使用p表示打印的标志。以下示例仅列出更改的行。
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt
执行上面的代码,你会得到以下结果:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
我们也可以将更改的行存储在另一个文件中。为了达到这个结果,使用w旗帜。以下示例显示了如何执行此操作。
[jerry]$ sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt
我们使用了相同的 SED 命令。让我们验证一下内容junk.txt文件。
执行上面的代码,你会得到以下结果:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
要执行不区分大小写的替换,请使用表示忽略大小写的 i 标志。以下示例执行不区分大小写的替换。
[jerry]$ sed -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt
执行上面的代码,你会得到以下结果:
3) The Alchemist, PAULO COELHO, 197
5) The Pilgrimage, PAULO COELHO, 288
到目前为止,我们只使用了前斜杠(/)字符作为分隔符,但我们也可以使用竖线(|)、at 符号(@)、插入符号(^)、感叹号(!)作为分隔符。以下示例显示如何使用其他字符作为分隔符。
让我们假设您需要替换路径/bin/sed和/home/jerry/src/sed/sed-4.2.2/sed.因此,您的 SED 命令如下所示:
[jerry]$ echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/jerry\/src\/sed\/sed-4.2.2\/sed/'
执行上面的代码,你会得到以下结果:
/home/jerry/src/sed/sed-4.2.2/sed
我们可以使这个命令更具可读性和易于理解。让我们使用竖线(|)作为分隔符并查看结果。
[jerry]$ echo "/bin/sed" | sed 's|/bin/sed|/home/jerry/src/sed/sed-4.2.2/sed|'
执行上面的代码,你会得到以下结果:
/home/jerry/src/sed/sed-4.2.2/sed
的确!我们得到了相同的结果,并且语法更具可读性。同样,我们可以使用“at”符号(@)作为分隔符,如下所示:
[jerry]$ echo "/bin/sed" | sed 's@/bin/sed@/home/jerry/src/sed/sed-4.2.2/sed@'
执行上面的代码,你会得到以下结果:
/home/jerry/src/sed/sed-4.2.2/sed
除此之外,我们还可以使用 caret(^) 作为分隔符。
[jerry]$ echo "/bin/sed" | sed 's^/bin/sed^/home/jerry/src/sed/sed-4.2.2/sed^'
执行上面的代码,你会得到以下结果:
/home/jerry/src/sed/sed-4.2.2/sed
我们还可以使用感叹号 (!) 作为分隔符,如下所示:
[jerry]$ echo "/bin/sed" | sed 's!/bin/sed!/home/jerry/src/sed/sed-4.2.2/sed!'
执行上面的代码,你会得到以下结果:
/home/jerry/src/sed/sed-4.2.2/sed
通常,反斜杠 (/) 用作分隔符,但有时将其他支持的分隔符与 SED 一起使用会更方便。