关于 awk 和整数到 ASCII 字符的转换
About awk and integer to ASCII character conversion
只是为了确定一下,我真的可以使用 awk(至少是 Gnu awk)转换:
从八进制到 ASCII 通过:
print "1" # or a="1"
A
从十六进制到 ASCII:
print "\x41" # or b="\x41"
B
但是从十进制到 ASCII 我必须:
$ printf "%c\n", 67 # or c=sprintf("%c", 67)
C
我错过的那个 RTFM(备忘录)中没有秘密 print "\?67"
?
我正在尝试从 [=16=]="aabccc"
获取字符频率,例如:
for(i=141; i<143; i++) a=a gsub("\"i, ""); print a
213
但使用小数(而不是上面示例中的八进制)。十进制方法看起来很长:
$ cat foo
aabccc
$ awk '{for(i=97;i<=99;i++){c=sprintf("%c",i);a=a gsub(c,"")} print a}' foo
213
习惯了here。
不,\nnn
是八进制而 \xnn
是十六进制 - 这就是包含不能按原样包含在字符串中的字符的全部内容,您应该始终使用八进制,而不是十六进制,鲁棒性表示(参见,例如,http://awk.freeshell.org/PrintASingleQuote)。
我不明白你问题的最后一部分,你在其中陈述了你试图用这个做什么 - 提供简洁、可测试的示例输入和预期输出,我相信有人可以帮助你做到这一点正确的方法,不管是什么。
这是你想要做的吗?
$ awk 'BEGIN{for (i=0141; i<0143; i++) print i}'
97
98
查找 table 是在 "AWK only".
中解决此问题的唯一方法(直接将 CHAR 转换为 ASCII DECIMAL)
您可以简单地使用 sprintf() 将 ASCII DECIMAL 转换为 CHAR。
您可以创建一个查找 table 通过遍历每个已知的
ascii 字符并将它们存储在一个数组中,其中键是字符,值是该字符的 ascii 值。
您可以在 AWK 中使用 sprintf() 来获取每个小数点的字符。
然后可以将char传给数组得到对应的
又是十进制。
在这个例子中,使用awk。
- 我们循环遍历所有 256 个字符,打印出每个字符。
- 我们将生成的字符串分成一系列行,每行有一个字符。
- 我们在 awk 中构建一个 table 的 256 个字符(在 BEGIN 中),然后将每个输入字符输入以查找每个字符。
- 最后我们打印出输入中每个字符的代码。
awk 'BEGIN{
for(n=0;n<256;n++)
print sprintf("%c",n)
}' | awk '{
for (i=0; ++i <= length([=10=]);)
printf "%s\n", substr([=10=], i, 1)
}' | awk 'BEGIN{
for(n=0;n<256;n++)
ord[sprintf("%c",n)]=n
}{
print ord[]
}'
反过来也可以,我们查找字符代码列表。
awk 'BEGIN{
for(n=0;n<256;n++)
print sprintf("%s",n)
}' | awk 'BEGIN{
for(n=0;n<256;n++)
char[n]=sprintf("%c",n)
}{
print char[]
}'
注意:第二个示例可能会在高 ascii 范围 (> 128) 中打印出大量垃圾,具体取决于您使用的字符集。
如果正如您在问题末尾所说的那样,您只是想计算字符的出现频率,我只是 assemble 一个数组。
$ awk '{for(i=1;i<=length([=10=]);i++) a[substr([=10=],i,1)]++} END{for(i in a) printf "%d %s\n",a[i],i}' <<<$'aabccc\ndaae'
1 d
1 e
4 a
1 b
3 c
注意,这也支持多行输入。
我们正在遍历每一行输入,递增一个计数器,该计数器是一个以相关字符为键的数组下标。
我希望这种方法比应用正则表达式来计算每个有趣字符的替换更高效,但我没有做过任何速度比较测试(当然这取决于你的集合有多大有兴趣)。
虽然这个答案没有解决您最初的问题,但我希望它能提供一种更好的方法来解决这个问题。
(感谢您在问题中包含最后的细节。XY problems 在这里太频繁了。)
注意:第二个示例可能会在高 ascii 范围 (> 128) 中打印出大量垃圾,具体取决于您使用的字符集。
这可以通过对 128-255 使用八进制代码 \200 - \377 来规避。
IIRC 字节 C0 C1 F5 F6 F7 F8 F9 FA FB FC FD FE FF 不应存在于正确编码的 UTF-8 文档中(或尚未指定)。 FE 和 FF 可能与 UTF16 字节顺序标记重叠,但由于世界已经标准化 UTF-8,所以今天这应该不是问题。
只是为了确定一下,我真的可以使用 awk(至少是 Gnu awk)转换:
从八进制到 ASCII 通过:
print "1" # or a="1"
A
从十六进制到 ASCII:
print "\x41" # or b="\x41"
B
但是从十进制到 ASCII 我必须:
$ printf "%c\n", 67 # or c=sprintf("%c", 67)
C
我错过的那个 RTFM(备忘录)中没有秘密 print "\?67"
?
我正在尝试从 [=16=]="aabccc"
获取字符频率,例如:
for(i=141; i<143; i++) a=a gsub("\"i, ""); print a
213
但使用小数(而不是上面示例中的八进制)。十进制方法看起来很长:
$ cat foo
aabccc
$ awk '{for(i=97;i<=99;i++){c=sprintf("%c",i);a=a gsub(c,"")} print a}' foo
213
习惯了here。
不,\nnn
是八进制而 \xnn
是十六进制 - 这就是包含不能按原样包含在字符串中的字符的全部内容,您应该始终使用八进制,而不是十六进制,鲁棒性表示(参见,例如,http://awk.freeshell.org/PrintASingleQuote)。
我不明白你问题的最后一部分,你在其中陈述了你试图用这个做什么 - 提供简洁、可测试的示例输入和预期输出,我相信有人可以帮助你做到这一点正确的方法,不管是什么。
这是你想要做的吗?
$ awk 'BEGIN{for (i=0141; i<0143; i++) print i}'
97
98
查找 table 是在 "AWK only".
中解决此问题的唯一方法(直接将 CHAR 转换为 ASCII DECIMAL)您可以简单地使用 sprintf() 将 ASCII DECIMAL 转换为 CHAR。
您可以创建一个查找 table 通过遍历每个已知的 ascii 字符并将它们存储在一个数组中,其中键是字符,值是该字符的 ascii 值。
您可以在 AWK 中使用 sprintf() 来获取每个小数点的字符。
然后可以将char传给数组得到对应的 又是十进制。
在这个例子中,使用awk。
- 我们循环遍历所有 256 个字符,打印出每个字符。
- 我们将生成的字符串分成一系列行,每行有一个字符。
- 我们在 awk 中构建一个 table 的 256 个字符(在 BEGIN 中),然后将每个输入字符输入以查找每个字符。
- 最后我们打印出输入中每个字符的代码。
awk 'BEGIN{ for(n=0;n<256;n++) print sprintf("%c",n) }' | awk '{ for (i=0; ++i <= length([=10=]);) printf "%s\n", substr([=10=], i, 1) }' | awk 'BEGIN{ for(n=0;n<256;n++) ord[sprintf("%c",n)]=n }{ print ord[] }'
反过来也可以,我们查找字符代码列表。
awk 'BEGIN{ for(n=0;n<256;n++) print sprintf("%s",n) }' | awk 'BEGIN{ for(n=0;n<256;n++) char[n]=sprintf("%c",n) }{ print char[] }'
注意:第二个示例可能会在高 ascii 范围 (> 128) 中打印出大量垃圾,具体取决于您使用的字符集。
如果正如您在问题末尾所说的那样,您只是想计算字符的出现频率,我只是 assemble 一个数组。
$ awk '{for(i=1;i<=length([=10=]);i++) a[substr([=10=],i,1)]++} END{for(i in a) printf "%d %s\n",a[i],i}' <<<$'aabccc\ndaae'
1 d
1 e
4 a
1 b
3 c
注意,这也支持多行输入。
我们正在遍历每一行输入,递增一个计数器,该计数器是一个以相关字符为键的数组下标。
我希望这种方法比应用正则表达式来计算每个有趣字符的替换更高效,但我没有做过任何速度比较测试(当然这取决于你的集合有多大有兴趣)。
虽然这个答案没有解决您最初的问题,但我希望它能提供一种更好的方法来解决这个问题。
(感谢您在问题中包含最后的细节。XY problems 在这里太频繁了。)
注意:第二个示例可能会在高 ascii 范围 (> 128) 中打印出大量垃圾,具体取决于您使用的字符集。
这可以通过对 128-255 使用八进制代码 \200 - \377 来规避。
IIRC 字节 C0 C1 F5 F6 F7 F8 F9 FA FB FC FD FE FF 不应存在于正确编码的 UTF-8 文档中(或尚未指定)。 FE 和 FF 可能与 UTF16 字节顺序标记重叠,但由于世界已经标准化 UTF-8,所以今天这应该不是问题。