流编辑器 - 字符串

替换命令

任何文本编辑器中都会出现"查找和替换"等文本替换操作.在本节中,我们将说明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 文件的内容.

[jerry]$ cat 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


到目前为止,我们只使用了预言(/)字符作为分隔符,但我们也可以使用竖线(|),符号(@),插入符号(^),感叹号(!)作为分隔符.以下示例显示如何将其他字符用作分隔符.

我们假设您需要将路径/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


除此之外,我们可以使用插入符号(^)作为分隔符.

[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的其他支持的分隔符更方便.

创建子字符串

我们学习了强大的替代命令.让我们看看是否可以从匹配的文本中找到子字符串.让我们在一个例子的帮助下理解如何做到这一点.

让我们考虑以下文字:

[jerry]$ echo "Three One Two"


假设我们必须将它排列成一个序列.意思是,它应首先打印一个,然后打印两个,最后打印三个.下面的单行代表是必要的.

echo "Three One Two" | sed 's|\(\w\+\) \(\w\+\) \(\w\+\)|\2 \3 \1|'


请注意,在上面的示例中,竖线(|)用作分隔符.

In SED,子串可以使用分组运算符指定,并且必须以转义字符为前缀,即 \( \).

\w 是一个匹配任何字母,数字或下划线的正则表达式,"+"用于匹配多个字符.换句话说,正则表达式 \(\\\ + \)匹配输入字符串中的单个单词.

在输入字符串中,有三个单词用空格分隔,因此有三个正则表达式用空格分隔.第一个正则表达式存储第一个单词,即三个,第二个存储单词一个,第三个存储单词两个

这些子串由 \N,引用,其中N是子串号.因此, \2 打印第二个子串,即 One; \ n 打印第三个子字符串,即 2; \1 打印第一个子字符串,即 3

让我们用逗号(,)分隔这些单词并相应地修改正则表达式.

[jerry]$ echo "Three,One,Two" | sed 's|\(\w\+\),\(\w\+\),\(\w\+\)|\2,\3,\1|'


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

One,Two,Three


注意现在正则表达式中有逗号(,)而不是空格.

字符串替换标志(仅限GNU SED)

在上一节中,我们看到了替换命令的一些示例. GNU SED提供了一些特殊的转义序列,可用于替换字符串.请注意,这些字符串替换标志是GNU特定的,可能不适用于SED的其他变体.这里我们将讨论字符串替换标志.

  • \ L:在替换字符串中指定\L时,它将\L之后的单词的所有剩余字符视为小写字符.例如,字符"ULO"被视为小写字符.

[jerry]$ sed -n 's/Paulo/PA\LULO/p' books.txt


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

3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288


  • \ u:在替换字符串中指定\ u时,它会将\ u之后的直接字符视为大写字母.在以下示例中,\ u在字符"a"和"o"之前使用.因此,SED将这些字符视为大写字母.

[jerry]$ sed -n 's/Paulo/p\uaul\uo/p' books.txt


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

3) The Alchemist, pAulO Coelho, 197 
5) The Pilgrimage, pAulO Coelho, 288


  • \ U:在替换字符串中指定\ U时,它会在\之后处理该单词的所有剩余字符U为大写字符.

[jerry]$ sed -n 's/Paulo/\Upaulo/p' books.txt


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

3) The Alchemist, PAULO Coelho, 197 
5) The Pilgrimage, PAULO Coelho, 288


  • \ E:此标志应与\L或\U一起使用.它会停止由标志\L或\ U启动的转换.在下面的示例中,只有第一个单词被替换为大写字母.

[jerry]$ sed -n 's/Paulo Coelho/\Upaulo \Ecoelho/p' books.txt


在执行上面的代码时,你会得到结果如下:

3) The Alchemist, PAULO coelho, 197 
5) The Pilgrimage, PAULO coelho, 288