如何使用不同的字符集获取uniq字符串

Vik*_*lin 6 linux bash awk character-encoding

我有一个文件1.txt

$ cat 1.txt 
page1
?age1
Run Code Online (Sandbox Code Playgroud)

但:

$ 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
Run Code Online (Sandbox Code Playgroud)

字符串有不同的字符集.因为它我不能用我知道的方法得到唯一的字符串:

$ cat 1.txt | sort | uniq -c | sort -rn
      1 ?age1
      1 page1
Run Code Online (Sandbox Code Playgroud)

那么,你能帮助我找到在我的情况下如何获得唯一字符串的方法吗?PS Prefer解决方案只能使用linux命令行/ bash/awk.但是如果你有另一种编程语言的解决方案,我也会喜欢它.

UPD.awk '!a[$0]++' Input_file不工作,pic:

在此输入图像描述

Ada*_*atz 1

粗略地检查一下我们这里的内容:

\n\n
$ cat 1.txt\npage1\n\xd1\x80age1\n$ hd 1.txt\n00000000  70 61 67 65 31 0a d1 80  61 67 65 31 0a           |page1...age1.|\n0000000d\n
Run Code Online (Sandbox Code Playgroud)\n\n

正如问题评论中所指出的,第二个“\xd1\x80age1”确实与前一个“page1”不同,原因是:这不是拉丁语p,而是西里尔语\xd1\x80,因此唯一性过滤器应该调用除非您事先对文本进行规范化,否则它们将作为单独的内容出现。

\n\n

iconv 在这里不起作用。 uconv(例如apt install icu-devtools在 Debian/Ubuntu 上)会让你接近,但它的音译映射是基于语音而不是相似的字符,所以当我们音译这个例子时,西里尔字母\xd1\x80变成了拉丁字母r

\n\n
$ uconv -x Cyrillic-Latin 1.txt\npage1\nrage1\n
Run Code Online (Sandbox Code Playgroud)\n\n

另请参阅这些更复杂的uconv命令,它们具有类似的结果。

\n\n

ICU uconv 手册页指出

\n\n
\n

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

\n
\n\n

这意味着有人可以使用“ICU 音译规则格式”来指定相似的字符映射。当然,按照这个速度,您可以使用任何您想要的语言。

\n\n

我还尝试了 perl\'s Text::Unidecode,但它有它自己的(类似)问题:

\n\n
$ perl -Mutf8 -MText::Unidecode -pe \'$_ = unidecode($_)\' 1.txt\npage1\nNEURage1\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n