假设我有一个包含以下内容的文件:
VSDmaMapInfo
VSDmaMapInfo::
VSDmaMapInfo;
VSPortErr
VSPortErr,
VSPortErr::
排序后我想要输出
VSDmaMapInfo
VSPortErr
有没有办法使用grep,awk,uniq或任何其他工具等
非常感谢你的帮助。
答案 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{$_}++
。
要删除该行上第一个标点字符后的任何内容,请将替换替换为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
说明:
RS
)设置为此正则表达式,我们摆脱了尾随标点符号,因此记录即$0
是一个单词。a
中统计这些字数。
a[$0]
为0,!a[$0]
计算结果为true,则单词将被打印出来。否则,它不会打印出来。