首页 > 解决方案 > 消除跨行重复的单词

问题描述

我想要一个 sed 脚本,它可以消除文本文件中一行或多行的重复单词。例如:

this is is is a text file file it is littered with duplicate words
words words on one or more lines lines
lines
  lines

应转换为:

this is a text file it is littered with duplicate words
on one or more lines

此 awk 脚本产生正确的输出:

{
    for (i = 1; i <= NF; i++) {
        word = $i

        if (word != last) {
            if (i < NF) {
                next_word = $(i+1)

                if (word != next_word) {
                    printf("%s ", word)
                }
            } else {
                printf("%s\n", word)
            }
        }
    }

    last = word
}

但我真的很想要一个 sed “单线”。

标签: sed

解决方案


这适用于 GNU sed,至少对于示例输入:

$ sed -Ez ':a;s/(\<\S+)(\s+)\1\s+/\1\2/g;ta' infile
This is a text file and is littered with duplicate words
on one or more lines

-E选项只是为了避免必须转义捕获组括号和+量词。

-z将输入视为空字节分隔,即单行。

然后命令的结构为

:a      # label
s///g   # substitution
ta      # jump to label if substitution did something

替换是这样的:

s/(\<\S+)(\s+)\1\s+/\1\2/g
  • 第一个捕获组:(\<\S+)– 一个完整的单词(单词边界的开始,一个或多个非空格字符
  • 第二个捕获组:(\s+)- 在第一个单词之后的任意数量的空格
  • \1\s+– 第一个单词加上后面的空格

这会保留第一个单词后的空格并丢弃重复后的空格。

请注意,-E-z\<\S都是\sPOSIX sed 的 GNU 扩展。


推荐阅读