将 ASCII 字符映射到十六进制代码的 awk 命令不起作用

将 ASCII 字符映射到十六进制代码的 awk 命令不起作用

我正在尝试使用 awk,我认为编写一个小程序将每个 ASCII 字符与其十六进制代码映射是一个很酷的主意。这就是我到目前为止所做的:

该字符串是:

abshdfitiggwigiwjirjgiejrigjr

我保持简单,不包括回车或制表符等

我将其转储到一个用逗号分隔的文件中,以便我可以使用 awk 的 -F 标志将它们识别为字段:

a,b,s,h,d,f,i,t,i,g,g,w,i,g,i,w,j,i,r,j,g,i,e,j,r,i,g,j,r,

我对同一文件的十六进制转储做了同样的事情:

61,62,73,68,64,66,69,74,69,67,67,77,69,67,69,77,6a,69,72,6a,67,69,65,6a,72,69,67,6a,72,0a,

我现在想,因为它们都有相同的 NF,所以会更容易,所以我尝试了以下 awk 命令:

awk -F ',' '{for(i=1;i<NF;i++){sum[$i]=$i}} END {for(char in sum) { print char, sum[char]} } ' line.txt linebits.txt 

其中 line.txt 和 linebits.txt 对应于正确的文件

输出如下:

62 62
h h
72 72
i i
0a 0a
64 64
73 73
j j
w w
65 65
74 74
66 66
67 67
77 77
68 68
a a
69 69
b b
6a 6a
d d
e e
r r
f f
s s
61 61
g g
t t

这当然是有道理的,因为 sum[$i]=$i 只是在做 sum[g]=g ,并且我打印的两者是相同的

我知道为什么它显示这个输出,但我不知道如何修复它。

是否可以指定我想要哪个文件?是否可以获取标准输入的索引?我知道这听起来很疯狂哈哈

我想要的输出是:

char - hex code
char - hex code
.....

答案1

听起来您的目标是学习(关于)awk,而不是简单地获取 ASCII 表,而其他答案很容易获得该表。

为此,您不需要任何输入文件;您可以直接显示所有可打印字符

awk 'BEGIN{ for(i=32;i<127;i++) printf("%02x %c\n",i,i) }'

(这会生成一长列,就像您的尝试一样;如果您想要多列,则将其作为练习。)

OTOH,如果您想组合两行中的字段对 - 可以是任何值,而不仅仅是字符及其十六进制:

awk [-Fasneeded] 'NR==1 { for(i=1;i<=NF;i++) save[i]=$i; next }
  { for(i=1;i<=NF;i++) print save[i],$i }' file ...
# linebreak for ease of reading, may be omitted in use

无论这两行来自两个文件(如您的情况)还是来自一个文件,这都有效。如果您有两行以上,则会将第 1 行到每个后续行的字段配对,这种模式对于 CSV 类型文件通常有意义,这些文件在第 1 行上有一个标题,其中包含每列的名称,后跟可变数量的行每列中都有数据。

这也保留了包括任何欺骗在内的顺序。为了消除欺骗但保持秩序:

awk [-Fasneeded] 'NR==1 { for(i=1;i<=NF;i++) save[i]=$i; next } 
  { for(i=1;i<=NF;i++) if(!dupe[$i]++) print save[i],$i ;delete dupe }' file ...
# the delete dupe can be omitted in the two-line case

如果你真的想要由此创建的随机顺序for in也是可能的,但这对我来说没有意义。一些有用诸如数字顺序或字母顺序(消除重复)之类的顺序可能是有意义的。

答案2

您已经获得了更简单的方法,但由于这里的目标似乎是学习 awk,因此我将如何使用您描述的方法来做到这一点。首先,我不会使用,分离,使用线条来完成类似的事情会更容易。然后我们可以使用NRFNR特殊变量来连接这两个文件。NR保存当前输入行号,而FNR输入行号当前正在读取的文件的。因此,如果我们给出awk两个文件,每个文件有 2 行,那么NR将从 到14但在读取第二个文件的第一行时,FNR将从 到 然后回到12然后。12

把它们放在一起,我们可以做到:

## get the characters, one per line
printf '%s\n' {a..z} > chars

## get the 2byte codes as you had in the question. I am sure
## there is a simpler way, but this is the best I could come up with
hexdump -x chars | tr -s ' ' '\n' | sed -n 's/^0a//p' > codes

有了这些文件,我们可以执行以下操作:

## Use awk to print them in pairs
$ awk '{ if(NR==FNR){chars[FNR]=$1} else{ print chars[FNR],$1}}' chars codes
a 61
b 62
c 63
d 64
e 65
f 66
g 67
h 68
i 69
j 6a
k 6b
l 6c
m 6d
n 6e
o 6f
p 70
q 71
r 72
s 73
t 74
u 75
v 76
w 77
x 78
y 79
z 7a

当然,这也可以使用 来完成paste,但没关系:

$ paste chars codes
a   61
b   62
c   63
d   64
e   65
f   66
g   67
h   68
i   69
j   6a
k   6b
l   6c
m   6d
n   6e
o   6f
p   70
q   71
r   72
s   73
t   74
u   75
v   76
w   77
x   78
y   79
z   7a

答案3

如果您使用 GNU awk,那么您可以包含扩展库ordchr

echo abshdfitiggwigiwjirjgiejrigjr |
    awk -lordchr -F '' '{for(i=1;i<=NF;i++)printf "%c %x\n", $i, ord($i)}'
a 61
b 62
s 73
h 68
...

ord()-函数,将 char 转换为十进制
printf "%x", ord($i)-将十进制转换为十六进制
此外:chr()-将小数转换为字符

答案4

为什么不使用现有的程序而不是编写自己的程序呢?我建议ascii来自埃里克·S·雷蒙德。

要使用上述命令输出 ASCII 字符的十六进制值,请执行以下命令:ascii -x.

输出示例:

   00 NUL    10 DLE    20      30 0    40 @    50 P    60 `    70 p 
   01 SOH    11 DC1    21 !    31 1    41 A    51 Q    61 a    71 q 
   02 STX    12 DC2    22 "    32 2    42 B    52 R    62 b    72 r 
   03 ETX    13 DC3    23 #    33 3    43 C    53 S    63 c    73 s 
   04 EOT    14 DC4    24 $    34 4    44 D    54 T    64 d    74 t 
   05 ENQ    15 NAK    25 %    35 5    45 E    55 U    65 e    75 u 
   06 ACK    16 SYN    26 &    36 6    46 F    56 V    66 f    76 v 
   07 BEL    17 ETB    27 '    37 7    47 G    57 W    67 g    77 w 
   08 BS     18 CAN    28 (    38 8    48 H    58 X    68 h    78 x 
   09 HT     19 EM     29 )    39 9    49 I    59 Y    69 i    79 y 
   0A LF     1A SUB    2A *    3A :    4A J    5A Z    6A j    7A z 
   0B VT     1B ESC    2B +    3B ;    4B K    5B [    6B k    7B { 
   0C FF     1C FS     2C ,    3C <    4C L    5C \    6C l    7C | 
   0D CR     1D GS     2D -    3D =    4D M    5D ]    6D m    7D } 
   0E SO     1E RS     2E .    3E >    4E N    5E ^    6E n    7E ~ 
   0F SI     1F US     2F /    3F ?    4F O    5F _    6F o    7F DEL

相关内容