25、sed 字符串子串

前面,我们已经简单学习了下 sed 中的 替换命令 s。 见到本章节之前,我以为这个替换命令就是简简单单的。

可没想到 GNU sed 的 替换命令 功能强大,竟然支持 正则表达式分组和反向引用功能

不过有点遗憾的是,这些功能只有 GNU sed 支持,苹果电脑自带的 sed 是万万支持不了的。

正则表达式分组和反向引用功能 允许我们在匹配的功能之外,捕获匹配到的字符串子串,然后再对这些子串进行处理。

纯文字描述有点拗口了,我们来看一个范例吧。

假设我们有一行文字

[www.ddkk.com]$ echo "Three One Two"

其实就是使用 空格 隔开的简单的三个单词。

现在我们要这三个单词按行显示,也就是每个单词独占一行。

最简单的做法就是直接将 空格 替换为换行符。

[www.ddkk.com]$ echo "Three One Two" | sed 's/ /\n/'

但结果并不是我们想要的

Three
One Two

怎么办呢?

没有办法了吗?

不是的,我们可以使用 正则表达式分组和反向引用功能

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

运行结果如下

One
Two
Three

哈哈,是不是看到了和之前不一样的 sed 替换正则表达式?

我们所熟悉的 / 变成了 竖线 | 了。

sed中,竖线 | 也可以作为 模式 的分隔符。

sed中的字符串子串使用 正则表达式分组功能和反向引用功能 来实现。

细细的说就是,sed 中的字符串子串使用 正则表达式分组功能 来对输入行进行正则匹配并分组,然后使用 正则表达式反向引用功能 来引用前面分组好的内容。

注意,sed 中的正则表达式分组功能中的 **小括号 () 需要转义,也就是使用 ( 和 )。

  • \w

\w 是正则表达式的一个 元字符。\w 用于表示 ANSI 中的任何单个 数字、字母、下划线

也就是说,\w 可以表示下面列出的任何单个字符

0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+

  • 在正则表达式中用于表示 一个或更多字符。 任何字符或字符串后面出现 + 号,则表示这个字符或字符串需要最少出现一次。

因此正则表达式 (\w+) 用于表示可以匹配一个以上的任意字符(上面出现的任意字符)

  • \n

对于 \n,如果你非常熟悉正则表达式,那么它就不陌生了。

\n 在正则表达式中被称为 正则表达式反向。其中 n 是指第几个 圆括号 () 所匹配的内容。

比如说 One,Two,Three 和正则表达式 (\w+),(\w+),(\w+) ,\1 表示 One,\2 表示 Two,\3 表示 Three。

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

运行结果如下

One
Two
Three

你可能会问 \0 表示什么,它表示的是匹配的全部内容,也就是 One,Two,Three。

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

运行结果如下

One,Two,Three
One
Two
Three

范例

下面的sed 命令,我们使用 逗号(,) 正则表达式分隔字符串,然后使用正则表达式反向引用 \n 将各个子串顺序调换一下

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

运行以上 sed 命令,输出结果如下

One,Two,Three

注意

上面的范例,分隔符已经改成了 逗号(,) ,而不是之前的 **空格()。