前面,我们已经简单学习了下 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
注意
上面的范例,分隔符已经改成了 逗号(,) ,而不是之前的 **空格()。