sed单词重复问题

sed单词重复问题

我是 sed 的新手,正在尝试学习一些东西。然而,在使用 sed 删除重复的单词时,我遇到了一个无法解决的问题:

echo "abc abc def ghi ijk ijk" | sed 's/\([a-z][a-z]*\) \1/\1/g'

输出

abc def ghijk ijk

每当一个单词以与下一个单词的第一个字母相同的字母结尾时,它都会这样做。我做错了什么?

答案1

问题是,正则表达式可以匹配部分单词。在您展示的示例中,它将i一个单词末尾的 与i下一个单词开头的 匹配。解决方案是坚持让正则表达式匹配整个单词:

$ echo "abc abc def ghi ijk ijk" | sed 's/\<\([a-z][a-z]*\)\> \<\1\>/\1/g'
abc def ghi ijk

在 GNU sed 中,\<在单词的开头匹配,并\>在单词的结尾匹配。

更复杂的匹配

在问题的例子中,正则表达式匹配单个重复字符。i i下面是匹配的示例oat oat

$ echo "smoat oats" | sed 's/\([a-z][a-z]*\) \1/\1/g'
smoats

再次,通过坚持完整的单词来解决这个问题:

$ echo "smoat oats" | sed 's/\<\([a-z][a-z]*\)\> \<\1\>/\1/g'
smoat oats

简化

由于字母到空格的转换总是标记单词边界,因此上面正则表达式使用的部分\> \<是不必要的,因为正则表达式要求两边的字符都是字母。因此,我们可以使用:

$ echo "smoat oats" | sed 's/\<\([a-z][a-z]*\) \1\>/\1/g'
smoat oats

文档

有关 sed 及其正则表达式的精妙之处的更多信息,我推荐Grymoire教程. GNU sed 的终极参考是GNU sed 手册

相关内容