如何获取具有不同字符集的唯一字符串

6

我有一个文件1.txt

$ cat 1.txt 
page1
рage1

但是:
$ head -n1 1.txt | file -i -
/dev/stdin: text/plain; charset=us-ascii

$ head -n2 1.txt | tail -n1 | file -i -
/dev/stdin: text/plain; charset=utf-8

字符串有不同的字符集。因此,我无法用我知道的方法获得唯一的字符串:

$ cat 1.txt | sort | uniq -c | sort -rn
      1 рage1
      1 page1

那么,你能帮我找到在我的情况下如何获取唯一字符串的方法吗? 附注:请优先使用Linux命令行/ bash / awk解决方案。 但是如果您有另一种编程语言的解决方案,我也很乐意接受。

更新。 awk '!a[$0]++' Input_file 不起作用,图片:

enter image description here


1
@anubhava 的输出是M-QM-^@age1$ page1$ - Viktor Khilin
4
第一个不是p: "U+0440 р d1 80 CYRILLIC SMALL LETTER ER"。没有简单的解决方法,只能替换替换替换。 - James Brown
1
哦,天啊。@JamesBrown,你是对的,这确实是西里尔字母р,而不是英语中的p。问题太蠢了,谢谢!附言:你能告诉我,你从哪里得到这个信息的吗?"U+0440 р d1 80 CYRILLIC SMALL LETTER ER" - Viktor Khilin
3
我使用谷歌搜索了 utf8 编码中以 "d1 80" 开头的字符。 :D - James Brown
你尝试过使用 iconv 吗? - mvrma
显示剩余5条评论
1个回答

1
一次简要的检查显示我们拥有以下内容:
$ cat 1.txt
page1
рage1
$ hd 1.txt
00000000  70 61 67 65 31 0a d1 80  61 67 65 31 0a           |page1...age1.|
0000000d

正如问题评论中所指出的那样,第二个 "рage1" 确实与之前的 "page1" 不同,原因是:那不是拉丁字母 p,而是西里尔字母 р,因此,除非您事先对文本进行规范化处理,否则唯一性过滤器应将它们视为不同的内容。

在这里,iconv 无法解决问题。uconv(例如,在 Debian/Ubuntu 上使用 apt install icu-devtools)可以让您接近目标,但其转换映射基于语音而不是相似字符,因此,当我们对此示例进行转写时,西里尔字母 р 变成了拉丁字母 r

$ uconv -x Cyrillic-Latin 1.txt
page1
rage1

另请参阅这些更复杂的uconv命令,它们具有类似的结果。 ICU uconv手册指出:

uconv还可以在转换后对转换数据运行指定的音译,在这种情况下,音译将作为中间步骤发生,数据被转换为Unicode后。音译可以是分号分隔的音译器名称列表,也可以是ICU音译规则格式中任意复杂的规则集。

这意味着某人可以使用“ICU音译规则格式”来指定类似字符映射。当然,这样做的话,您可以使用任何语言。
我还尝试了perl的Text::Unidecode,但它有自己的(类似的)问题:
$ perl -Mutf8 -MText::Unidecode -pe '$_ = unidecode($_)' 1.txt
page1
NEURage1

在某些情况下,这可能效果更好,但显然这不是其中之一。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接