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:
粗略地检查一下我们这里的内容:
\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\nRun Code Online (Sandbox Code Playgroud)\n\n正如问题评论中所指出的,第二个“\xd1\x80age1”确实与前一个“page1”不同,原因是:这不是拉丁语p,而是西里尔语\xd1\x80,因此唯一性过滤器应该调用除非您事先对文本进行规范化,否则它们将作为单独的内容出现。
iconv 在这里不起作用。 uconv(例如apt install icu-devtools在 Debian/Ubuntu 上)会让你接近,但它的音译映射是基于语音而不是相似的字符,所以当我们音译这个例子时,西里尔字母\xd1\x80变成了拉丁字母r:
$ uconv -x Cyrillic-Latin 1.txt\npage1\nrage1\nRun Code Online (Sandbox Code Playgroud)\n\n另请参阅这些更复杂的uconv命令,它们具有类似的结果。
ICU uconv 手册页指出
\n\n\n\n\nuconv还可以对转码后的数据运行指定的音译,在这种情况下,音译将作为数据转码为 Unicode 后的中间步骤进行。音译可以是分号分隔的音译者名称列表,也可以是ICU 音译规则格式中任意复杂的规则集。
\n
这意味着有人可以使用“ICU 音译规则格式”来指定相似的字符映射。当然,按照这个速度,您可以使用任何您想要的语言。
\n\n我还尝试了 perl\'s Text::Unidecode,但它有它自己的(类似)问题:
\n\n$ perl -Mutf8 -MText::Unidecode -pe \'$_ = unidecode($_)\' 1.txt\npage1\nNEURage1\nRun Code Online (Sandbox Code Playgroud)\n\n在某些情况下这可能会更好,但显然这不是其中之一。
\n