如果有一个UTF-8编码的文件,其中包含多种语言的字符,如何计算它所包含的唯一字符数量,同时排除一些特定符号(例如:“!”,“@”,“#”,“。”)的计数?
bash$ perl -CSD -ne 'BEGIN { $s{$_}++ for split //, q(!@#.) }
$s{$_}++ || $c++ for split //;
END { print "$c\n" }' *.utf8
-CSD
的脚本等效语句是什么? - Joel Berger-CSD
是 use open qw(:std :utf8)
。 - tchristimport itertools, codecs
predicate = set('!@#.').__contains__
unique_char_count = len(set(itertools.ifilterfalse(
predicate, itertools.chain.from_iterable(codecs.open(filename, encoding="UTF-8")))))
import codecs
disallowed = set('!@#.')
unique_char_count = len(set(char for line in codecs.open(filename, encoding="UTF-8") for char in line
if char not in disallowed))
使用集合操作:
import codecs
unique = set()
any(unique.update(line) for line in codecs.open(filename, encoding="UTF-8"))
unique.difference_update('!@#.')
unique_char_count = len(unique)
.from_iterable
。我也加上了非 itertools 版本。 - agfopen
调用中指定编码。 - Niklas B.codecs.open
并指定了 UTF-8。 - agf使用集合的 Ruby:
require 'set'
string = 'ababbbababbabcdcccdbbaaba'
ignore = 'c'
(Set.new(string.chars) - Set.new(ignore.chars)).count
# => 3
string
是一个输入字符串ignore
是要忽略的字符组成的字符串string.chars
是字符串中字符的列表Set.new
用于生成一个集合-
表示两个集合之间的差异count
是结果集合中元素的数量ignore.chars
就足够了,无需转换为集合。 - steenslag另一个 Ruby 示例:
#encoding: utf-8
string = '@étude#@étude ฒณ!'
ignore = '!@#.'
p string.chars.to_a.uniq.join.delete(ignore).size #=>8
使用Perl单行命令:
echo -e "aba\ncfg!ഡ.#g" | perl -C7 -ne 'for(split(//)){if ($_ !~ /[!@#.]/) { print $_."\n"}}' | sort | uniq | wc -l
输出 7
如果您想忽略换行符:
echo -e "aba\ncfg!ഡ.#g" | perl -C7 -ne 'for(split(//)){if ($_ !~ /[!@#.\n]/) { print $_."\n"}}' | sort | uniq | wc -l
输出结果 6
我只是为了增加选择而提供这个不需要语言的选项:
sed 's/[!@#.]//g' /path/to/file | sed 's/./\0\n/g' | sort -u | wc -l
iconv -f utf-16 -t ascii sourcefile | sed 's/[!@#.]//g' /path/to/file | sed 's/./\0\n/g' | sort -u | wc -l
- paulsm4sed
使用\0
表示整个模式甚至使用\n
表示文字换行符是不可移植的,因为它们不是POSIX标准的一部分。还有Unicode的问题没有解决。 所以不需要语言就能做到这点,真是太棒了! :( 另一方面,像使用perl -CS -pe 's/(.)/$1\n/g'
这样的替换方法是可移植的,因为与sed
有许多彼此不兼容的版本不同,perl
的版本并不多。 - tchristtr -d
:)) - msb经过三个小时的研究,我用Python完成了这个任务。
fname = "temp.txt"
num_lines = 0
num_words = 0
num_chars = 0
num_uniq = 0
a = []
exclude = ",.@#$"
with open(fname, 'r') as f:
for line in f:
words = line.split()
for word in words:
char = list(word)
a = a + char
num_lines += 1
num_words += len(words)
num_chars += len(line)
print "Lines:%s\nWords:%s\nChars:%s" % (num_lines, num_words, num_chars)
num_uniq = len(set(a)-set(exclude))
print "Unique Characters:%d" % (num_uniq)
这里是输出结果
Lines:6
Words:74
Chars:385
Unique Characters:26
f=open('url.txt')
a=''
for x in f:
x=x.split(' ')
for y in x:
a+=y
unique=set(a)-set('@!#.') #add the characters that you wanna neglect in the second set
print(unique)
print('unique characters : ',len(unique))
假设url.txt包含:
Google --! google.com --! coolest search engine
facebook --! facebook.com --! biggest social network
yahoo --! yahoo.com --! biggest web portal
输出将是:
{'a', 'G', 'm', '\n', 'n', 'c', 'b', 'e', 'g', 'f', 'i', 'h', 'k', '-', 'l', 'o', 'p', 's', 'r', 't', 'w', 'y'}
unique characters : 22
''.join(''.join(x.split()) for x in f)
这样的东西,它会更快。请参阅我的答案以了解如何在不构建长字符串的情况下完成它。 - agf一个替代方案:
filename='/somewhere/my-file-in-utf8'
iconv -f UTF8 -t UTF16 $filename | tail -c +3 | \
perl -pi -e "s/\x00\@//g; s/\x00\!//g; s/\x00\#//g; s/\x00\.//g;" | \
od | cut -b 8- | xargs -n 1 | sort | uniq | wc -l