Sed 字符串

替换命令

诸如"find和replace"之类的文本替换操作在任何文本编辑器中都是常见的。在本节中,我们说明了SED如何执行文本替换。

[address1[,address2]]s/pattern/replacement/[flags]

在这里, address1 和 address2 分别是开始地址和结束地址,可以是行号或模式字符串,这两个地址都是可选参数。

在books.txt文件中,我们使用了逗号(,)分隔每一列,让我们使用竖线(|)分隔每一列,为此,用竖线(|)替换逗号(,)。

$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 )用作:

$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时,才用竖线(|)替换逗号(,)。

$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 '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使用 p 标志引用打印。以下示例仅列出更改的行。

$sed -n 's/Paulo Coelho/PAULO COELHO/p' books.txt

执行上述代码后,您将得到以下输出:

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

我们也可以将更改的行存储在另一个文件中。要获得此输出,请使用 w 标志。以下示例显示了如何执行此操作。

$sed -n 's/Paulo Coelho/PAULO COELHO/w junk.txt' books.txt

我们使用了相同的SED命令。让我们验证 junk.txt 文件的内容。

$cat junk.txt

执行上述代码后,您将得到以下输出:

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

要执行不区分大小写的替换,请使用i 标志,该标志表示忽略大小写。以下示例执行不区分大小写的替换。

$sed  -n 's/pAuLo CoElHo/PAULO COELHO/pi' books.txt

执行上述代码后,您将得到以下输出:

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

让我们假设您需要用 /home/cainiaojc/src/sed/sed-4.2.2/sed替换路径/bin/sed 。因此,您的SED命令看起来像这样:

$echo "/bin/sed" | sed 's/\/bin\/sed/\/home\/cainiaojc\/src\/sed\/sed-4.2.2\/sed/'

执行上述代码后,您将得到以下输出:

/home/cainiaojc/src/sed/sed-4.2.2/sed

我们可以使该命令更具可读性和易懂性。让我们使用竖线(|)作为定界符并查看输出。

$echo "/bin/sed" | sed 's|/bin/sed|/home/cainiaojc/src/sed/sed-4.2.2/sed|'

执行上述代码后,您将得到以下输出:

/home/cainiaojc/src/sed/sed-4.2.2/sed

确实!我们得到相同的输出,语法更易读。同样,我们可以使用" at"符号(@)作为分隔符,如下所示:

$echo "/bin/sed" | sed 's@/bin/sed@/home/cainiaojc/src/sed/sed-4.2.2/sed@'

执行上述代码后,您将得到以下输出:

/home/cainiaojc/src/sed/sed-4.2.2/sed 

除此之外,我们可以使用caret(^)作为分隔符。

$echo "/bin/sed" | sed 's^/bin/sed^/home/cainiaojc/src/sed/sed-4.2.2/sed^'

执行上述代码后,您将得到以下输出:

/home/cainiaojc/src/sed/sed-4.2.2/sed 

我们还可以使用感叹号(!)作为定界符,如下所示:

$echo "/bin/sed" | sed 's!/bin/sed!/home/cainiaojc/src/sed/sed-4.2.2/sed!'

执行上述代码后,您将得到以下输出:

/home/cainiaojc/src/sed/sed-4.2.2/sed 

通常,反斜杠(/)用作分隔符,但有时将其他受支持的分隔符与SED一起使用更方便。

创建字符串

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

让我们考虑以下文本:

$echo "Three One Two"

假设我们必须将其排列成一个序列。就是说,它应该先打印一个,然后打印两个,最后打印三个。以下一线需要帮助。

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

请注意,在以上示例中,竖线(|)用作分隔符。

在SED中,可以使用分组运算符指定子字符串,并且必须在子字符串前面加上转义字符,即\(和\)。

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

     \2 打印第二个子字符串,即 One;\3 打印第三个子字符串,即 Two; 和\1 打印第一个子字符串,即 Three

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

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

执行上述代码后,您将得到以下输出:

One,Two,Three

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

字符串替换

在上一节中,我们看到了替换命令的一些示例。 GNU SED提供了一些特殊的转义序列,可以在替换字符串中使用。

  • \L : 当\L的替换字符串被指定时,它将该单词之后的所有剩余字符都替换成小写字符。如字符" ULO"被视为小写字符。

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

执行上述代码后,您将得到以下输出:

3) The Alchemist, PAulo Coelho, 197
5) The Pilgrimage, PAulo Coelho, 288
  • \u : 在替换字符串中指定\u时,它将\u之后的立即字符视为大写字符。

$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之后的单词的所有剩余字符视为大写字符。

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

执行上述代码后,您将得到以下输出:

3) The Alchemist, PAULO Coelho, 197 
5) The Pilgrimage, PAULO Coelho, 288
  • \E : 此标志应与\L或\U一起使用。在下面的示例中,仅第一个单词被大写字母替换。

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

执行上述代码后,您将得到以下输出:

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