删除重复的单词,只打印出现这种情况的行

时间:2017-01-03 18:59:16

标签: regex bash sed

如果一个句子包含2个相同的连续单词,我在查看文件时遇到了挑战。如果是这样,你打印这个词;否则,你不打印句子。

示例:

abc2 1 def2 3 abc2
F4
--------------
dea 123 123 zy45
12 12
abc cd abc cd
xyz%$@! xyz%$@! kk
xyzxyz
abc h h h h

运行程序后,输出将为:

dea 123 zy45
12
xyz%$@! kk
abc h h h
3

这是我到目前为止所做的:

sed '/\([^\([^ ]\+\)[ ]\+\1]\)/d' F4 >|tmp

到目前为止我得到了这个,但这只是将具有双字的句子和不具有双字的句子分开。

2 个答案:

答案 0 :(得分:1)

您的sed表达非常准确。但是,它需要一些修改才能使它工作:

$ sed -nr 's/\b(\S+)\s+\1(\s|$)/\1/p' file
dea 123 zy45
12
xyz%$@! kk
abc h h h

您的想法是您已经实施的:将给定的字词与[^ ]匹配,看看您是否再次与\1匹配。我添加的所有内容都被\1替换,因此重复的块会消失。

使用[^ ]代替\S[ ],而不是\s。另请注意使用\b作为单词边界来防止fedorqui qui等误报以及使用\1(\s|$)来防止其他误报,例如hello helloa(感谢WalterA对于例子!)。注意\s|$用于匹配空格或行尾的用法; \b匹配任何无字字符,这使得它对xyz%$@! kk的情况无效。

为防止打印所有行,我们使用sed -n。这样,我们只打印(使用p)那些经过定义的正则表达式的文件。

请注意使用-r来摆脱所有转义为捕获组的内容。没有它,命令将是:

sed -n 's/\b\([^ ]\+\)[ ]\+\1/\1/p' file

让我们用更全面的输入来测试它:

$ cat a
abc2 1 def2 3 abc2
F4
--------------
dea 123 123 zy45
12 12
abc cd abc cd
xyz%$@! xyz%$@! kk
xyzxyz
fedorqui qui
hello helloa
abc h h h h
$ sed -nr 's/\b(\S+)\s+\1(\s|$)/\1/p' a
dea 123zy45
12
xyz%$@!kk
abc hh h

答案 1 :(得分:0)

我一直在寻找一个似乎很容易的sed解决方案。也许在这种情况下awk更好(F4是输入文件):

awk '{
        for (i=2; i<=NF; i++) { 
           if ($(i-1)==$i) { 
              $i="";
              printf("%s\n", $0);
              break;
           }
        }
     }' F4

我对这个解决方案并不满意,因为它会在删除加倍的单词后在$0中留下一个双FieldSep,但字面上OP确实没有看到空格或制表符也应该被删除。