从gawk中的Char返回uint值
我试图获取通过RS232接收的ASCII字符的值,将其转换为类似二进制的值 例如:从gawk中的Char返回uint值,awk,ord,Awk,Ord,我试图获取通过RS232接收的ASCII字符的值,将其转换为类似二进制的值 例如: 0xFF-->######## 0x01--> # 0x02--> # ... 我的问题是获取大于127的ASCII字符值 测试代码以获取int值: echo-e“\xFF”| gawk-l ordchr-e'{printf(“%c:%i”、ord($0)、ord($0))} 返回: � : -1 测试代码2: echo-e“\x61”| gawk-l ordchr-e'
0xFF-->########
0x01--> #
0x02--> #
...
我的问题是获取大于127的ASCII字符值
测试代码以获取int值:echo-e“\xFF”| gawk-l ordchr-e'{printf(“%c:%i”、ord($0)、ord($0))}
返回:
� : -1
测试代码2:echo-e“\x61”| gawk-l ordchr-e'{printf(“%c:%i”、ord($0)、ord($0))}
返回:
a:97
因此,我将值转换为无符号int的解决方案如下:
if(ord($0)<0)
{
new_char=ord($0)+256;
}
else new_char = ord($0)+0`
0xFF
返回:
� : 0
a : 97
0x61
返回:
� : 0
a : 97
有人能解释一下我的行为吗
我正在使用:GNU Awk 4.1.3,API:1.1(GNU MPFR 3.1.4-p1,GNU MP 6.1.1)
但我想知道是否有一种方法可以在gawk中直接将int转换为uint
实际上,awk中的任何字符串最终都是一个数字
字符串转换为数字,数字转换为字符串,
如果awk程序的上下文需要它。[…]字符串是
通过解释字符串的任何数字前缀转换为数字
如数字所示:“2.5”转换为2.5,“1e3”转换为1000,以及
“25fix”的数值为25。无法解释的字符串
当有效数字转换为零时
让我们做一个快速测试:
BEGIN {
print 0xff
print 0xff + 0
print 0xff +0.0
print "0xff"
}
# 255
# 255
# 255
# 0xff
因此,任何hex
都会自动解释为uint
。将int
转换为uint
是一个棘手的问题:通常,您应该将int
的模数转换为十六进制,然后将符号位添加为MSB(即,如果数字为非正)。但在awk中不需要这样做
请记住,转换是通过调用sprintf()
进行的,您可以通过CONVFMT
变量进行控制:
CONVFMT
控制数字到字符串转换的字符串
(见第节)。它的工作原理是
实际上,作为sprintf()函数的第一个参数传递
(见第节)。其默认值为
“%.6g”。CONVFMT是由POSIX标准引入的
请记住,区域设置可能会影响转换的执行方式,尤其是使用十进制分隔符时。有关更多信息,请参阅
有人能解释一下我的行为吗 我实际上无法复制它,但我怀疑这行代码:
# only first character is of interest
c = substr(str, 1, 1)
在您的示例中,第一个字符始终为0
,并且输出应始终相同。我正在测试这个
我再举一个例子:
BEGIN {
a = 0xFF
b = 0x61
printf("a: %d %f %X %s %c\n", a,a,a,a,a)
printf("b: %d %f %X %s %c\n", b,b,b,b,b)
}
# a: 255 255.000000 FF 255 ÿ
# b: 97 97.000000 61 97 a
在二进制模式下运行gawk
gawk-b
以阻止它预缝合UTF8代码点。通过//空字符串将其拆分,则结果数组中的每个点都将包含1字节宽的内容
另一方面,只需预先制作一个从0到256的数组。呆头呆脑的行为根本就不止于此。在我的例行gawk启动序列中,我从0x3134F
一直执行相同的自定义ord序列,直到零(大约210k左右)。不管出于什么原因,向后执行的原因是,有些代码点会出现一个gawk无法区分的相同字符。反向操作将确保为其分配最低的代码点。对于这种模式,我在常规utf8模式下运行它
对于您的场景,我将预先制作4个十六进制宽数组,从0x0000
到0xFFFF
,返回到它们的整数,然后对于每个0xZZ 0xWW
,将ZZWW
抛出到该查找字典中并返回整数
如果您只是尝试从128到255执行ord()
,通常不会这样做,因为128是unicode从2个字节开始的位置<代码>0x800开始3个字节,0x10000开始4个字节。我对那些将ascii扩展到256的代码不太熟悉——它们通常需要使用iconv
或类似的代码才能首先返回UTF-8
如果您想获取原始UTF8字节并试图计算出有多少缝合的UTF8代码点,只需删除所有内容0x80-0xBF
。残差的length()
是代码点的数量
在十进制术语中,从0到255的64个数字的4个范围中:
000-063
-ASCII
064-127
-ASCII
128-191
-UT8多字节连续编码(0x80 0xBF
)
192-255
-UTF8多字节字符的最高有效字节
0x80-0xBF
范围正好是\200-\277
。您可以使用AWK的任何正则表达式来查找这些(也适用于FS/RS等)。我花了很多时间手动编写utf8算法,然后才进行所有的位移位,后来我意识到我不需要这些来实现我的最终目标
如果您想在将上述逻辑与
mawk2
组合时计算utf8代码点,则可以轻松击败系统内置的wc-m
命令。在我2.5岁的笔记本电脑上,与一个满是unicode的1.83 GB平面文本文件相比,我用了大约19秒的时间来计算出12.9亿个utf8代码点,我自己也遇到了同样的问题。我最后使用了一个检测器,它是以unicode模式还是字节模式运行gawk(检查组成一个UTF8代码点的3个八进制值组合的length(),返回1或3)
然后,当它看到gawk unicode模式时,从gawk运行一个自定义shell命令,并使用unix printf打印出128-255字节,然后将其分块返回到gawk数组中。如果你需要的话,我可以在某个时候粘贴代码(但它太可怕了,所以我希望我不会因为它缺乏优雅而被指责)
因为UTF8中不存在像C0、C1或FF等这样的字节,不管您使用什么组合