我正在使用以下命令来 grep 十六进制代码 0900(而不是 अ)到 097F(而不是 व)的字符集范围。如何使用十六进制代码代替 अ 和 व?
bzcat archive.bz2 | grep -v '<[अ-व]*\s' | tr '[:punct:][:blank:][:digit:]' '\n' | uniq | grep -o '^[अ-व]*$' | sort -f | uniq -c | sort -nr | head -50000 | awk '{print "<w f=\""$1"\">"$2"</w>"}' > hindi.xml
我得到以下输出:
<w f="399651">और</w>
<w f="264423">एक</w>
<w f="213707">पर</w>
<w f="74728">कर</w>
<w f="44281">तक</w>
<w f="35125">कई</w>
<w f="26628">द</w>
<w f="23981">इन</w>
<w f="22861">जब</w>
...
我只想在上面的命令中使用十六进制代码而不是 अ 和 व。
如果根本不可能使用十六进制代码,我可以使用 unicode 而不是字符集('अ-व')的十六进制代码吗?
我使用的是Ubuntu 10.04
答案1
文本通常采用 UTF-8 编码;因此您必须使用 UTF-8 编码中使用的字节的十六进制值。
grep "["$'\xe0\xa4\x85'"-"$'\xe0\xa4\xb5'"]"
和
grep '[अ-व]'
是等价的,并且它们执行字符类/括号表达式基于语言环境的匹配(即匹配依赖于梵文脚本的排序规则(即匹配是不是“\u0905 和 \0935 之间的任何字符”,而是“天城文 A 和天城文 VA 之间的任何排序”;可能存在差异。
($'...'
是 bash、ksh 和 zsh 的“ANSI-C 转义字符串”语法。它只是一种更简单的输入字符的方法。您还可以使用\uXXXX
和\UXXXXXXXX
转义符直接询问 bash 和 zsh 中的代码点。)
另一方面,你有这个(注意-P):
grep -P "\xe0\xa4[\x85-\xb5]"
这将做一个二进制与那些相匹配字节值。
答案2
如果 shell 转义就足够了,您可以使用$'\xHH'
如下语法:
grep -v "<["$'\x09\x00'"-"$'\x09\x7F'"]*\s"
这对于您的用例来说足够了吗?
答案3
您写入的“十六进制”值0x0900
正是 UNICODE 代码点的值,也是十六进制的。
十六进制代码 0900(而不是 अ)
我相信你的意思是说十六进制UNICODE代码点:U0905
。
U-0900 处的字符不是您使用的字符:अ
。
该角色是U0905, 部分这个统一码页面,或列于这一页。
在bash
(Ubuntu 中默认安装)中,或直接使用以下程序:(/usr/bin/printf
但不能使用sh
printf),可以使用以下命令生成 Unicode 字符:
$ printf '\u0905'
अ
$ /usr/bin/printf '\u0905'
अ
但是,来自代码点编号的该字符可以由多个字节流表示,具体取决于使用的代码页。
很明显,它\U0905
是0x09 0x05
UTF-16(UCS-2 等)
和0x00 0x00 0x09 0x05
UTF-32 格式的。
它可能不明显,但在 utf-8 中它表示为0xe0 0xa4 0x85
:
$ /usr/bin/printf '\u0905' | od -vAn -tx1
e0 a4 85
如果您的控制台的区域设置类似于en_US.UTF-8
.
我谈论的是 shell,因为它是将字符串转换为应用程序接收到的内容。这:
grep "$(printf '\u0905')" file
使 grep “看到”您需要的字符。
要理解上面的行,您可以使用 echo:
$ echo grep "$(printf '\u0905')" file
grep अ file
然后,我们可以根据您的要求构建字符范围:
$ echo grep "$(printf '[\u0905-\u097f]')" file
grep [अ-ॿ] file
这回答了你的问题:
如何使用十六进制代码代替 अ 和 व?
答案4
我们想要将非 ASCII 左双引号和右双引号转换为常规双引号 (")。还将非 ASCII 单引号转换为常规单引号 (')。
在文件中查看它们(ubuntu bash shell):
$ grep -P "\x92" infile.txt (single)
$ grep -P "\x93" infile.txt (open double)
$ grep -P "\x94" infile.txt (close double)
翻译它们:
$ /bin/sed "s/\x92/'/g" a.txt > b.txt
$ /bin/sed 's/\x93/"/g' b.txt > c.txt
$ /bin/sed 's/\x94/"/g' c.txt > d.txt