2

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

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

排序后我希望输出为

VSDmaMapInfo
VSPortErr

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

非常感谢你的帮助。

4

7 回答 7

3
$ awk -F'[[:punct:]]' '{print $1}' file | sort -u
VSDmaMapInfo
VSPortErr
于 2013-06-14T10:46:44.563 回答
2

使用 GNU sed 排序内容的代码

sed -r '$!N;/(\w+)\W*\n\1\W*/!{s/(\w+).*/\1/;P};D' file
于 2013-06-15T13:44:58.517 回答
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

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

于 2013-06-14T08:34:58.557 回答
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{$_}++.

编辑2:

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

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

$ perl -ne'...' the-file.txt
于 2013-06-14T08:35:19.150 回答
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>
于 2013-06-14T09:05:26.063 回答
1

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

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

解释:

  1. 通过将记录分隔符 ( RS) 设置为此正则表达式,我们摆脱了尾随标点符号,因此记录 ie$0是一个单词。
  2. 我们记着 中的字数a
    • 如果单词不是重复的,a[$0]为 0,并且!a[$0]计算结果为真,则该单词被打印出来。否则,它不会被打印出来。
于 2013-06-14T09:24:56.447 回答
1

跳过重复的行,

perl -nE 's|\W||g; say unless $h{$_}++' file
于 2013-06-14T08:46:36.740 回答