剥离标点符号后删除重复的单词

时间:2013-06-14 08:30:19

标签: regex perl sed awk pattern-matching

假设我有一个包含以下内容的文件:

VSDmaMapInfo
VSDmaMapInfo::
VSDmaMapInfo;
VSPortErr
VSPortErr,
VSPortErr::

排序后我想要输出

VSDmaMapInfo
VSPortErr

有没有办法使用grep,awk,uniq或任何其他工具等

非常感谢你的帮助。

7 个答案:

答案 0 :(得分:3)

$ awk -F'[[:punct:]]' '{print $1}' file | sort -u
VSDmaMapInfo
VSPortErr

答案 1 :(得分:2)

使用GNU sed排序内容的代码

sed -r '$!N;/(\w+)\W*\n\1\W*/!{s/(\w+).*/\1/;P};D' file

答案 2 :(得分:1)

这可行:

$ tr -d "[[:punct:]]" < file | sort -u
VSDmaMapInfo
VSPortErr

解释

tr -d "[[:punct:]]"            < file         |    sort -u
   remove puntuation chars     read file          get unique

更新

来自你的评论:

  

我刚观察一下:如果输入包含VSDmaMapInfo :: callMe   它正在删除标点符号,但加入下一个单词,如   VSDmaMapInfocallMe。是否有可能将输出作为   VSDmapMapInfo只是没有附加下一个单词。

我们可以做到以下几点:

$ cat file
VSDmaMapInfo
VSDmaMapInfo::
VSDmaMapInfo;
VSDmaMapInfo;asdfs
VSPortErr
VSPortErr,
VSPortErr::

$ awk -F"[,:;]" '{print $1}' file | sort -u
VSDmaMapInfo
VSPortErr

也就是说,让awk在任何,:;之前打印第一个单词。然后,使用-u参数对其进行排序,以获得唯一数据。

答案 3 :(得分:1)

假设重复数据删除不会出现大小写不敏感,则以下Perl-oneliner会发出所需的输出:

perl -ne's/[[:punct:]]+$//;$h{lc $_}++ or print'

测试:

$ perl -ne's/[[:punct:]]+$//;$h{lc $_}++ or print' <<'END'
VSDmaMapInfo
VSDmaMapInfo::
VsDmaMapInfo;
VSPortErr
VsPortErr,
VsPortErr::
END

输出:

VSDmaMapInfo
VSPortErr

编辑:

对于区分大小写的匹配,请将$h{lc $_}++更改为$h{$_}++

EDIT2:

要删除该行上第一个标点字符后的任何内容,请将替换替换为s/[[:punct:]].*//

要使用文件调用单行程序,可以将输入文件列为命令行参数:

$ perl -ne'...' the-file.txt

答案 4 :(得分:1)

跳过重复的行,

perl -nE 's|\W||g; say unless $h{$_}++' file

答案 5 :(得分:1)

sed解决方案(基本上是sed + sort)

sed 's/[^[:alpha:]]//g' <file> |sort -u

另一种笨拙的awk解决方案

awk '{gsub(/[^[:alpha:]]/,""); a[$0]=1} END{for(var in a) print var}' <file>

另一个令人敬畏的纯粹bash解决方案(我喜欢玩bash:))

l=""
while read r
do
r=${r//[^[:alpha:]]/}
 if ! [[ $l =~ $r ]]
 then
 echo $r
 l="$l $r"
 fi
done < <file>

答案 6 :(得分:1)

如果你使用GNU awk,你可以使用多个字符作为记录分隔符(RS),所以你可以这样做:

awk '!a[$0]++' RS='[[:punct:]]*\n' test.txt

说明:

  1. 通过将记录分隔符(RS)设置为此正则表达式,我们摆脱了尾随标点符号,因此记录即$0是一个单词。
  2. 我们会在a中统计这些字数。
    • 如果单词不重复,a[$0]为0,!a[$0]计算结果为true,则单词将被打印出来。否则,它不会打印出来。