
私はawkを使用しようとしていますが、各ASCII文字を16進コードにマップする小さなプログラムを書くのが素晴らしいアイデアだと思いました。これが私がこれまでにしたことです:
文字列は次のとおりです
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,
同じファイルの16進ダンプで同じことをしました。
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 を実行していて、私が印刷する2つは同じだからです。
この出力が表示される理由はわかりますが、解決策がわかりません。
希望のファイルを指定できますか?標準入力のインデックスを取得できますか?クレイジーな音のように聞こえます。
私が望む出力は次のとおりです。
char - hex code
char - hex code
.....
答え1
あなたの目標は、単に他の答えで簡単に取得できるASCIIテーブルを取得するのではなく、awkを学ぶことです。
これには入力ファイルは必要ありません。印刷可能なすべての文字を直接表示できます。
awk 'BEGIN{ for(i=32;i<127;i++) printf("%02x %c\n",i,i) }'
(これを行うと、同じように長い列が1つ生成されます。複数の列が必要な場合は練習のままにしてください。)
OTOH、2行のフィールドのペアを結合したい場合は、文字と16進数だけでなく、任意の値にすることができます。
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
これは、2つの行が2つのファイル(あなたの場合のように)から出てくるか、1つのファイルから出てくるかにかかわらず機能します。行が3つ以上の場合、行1から各後続行までのフィールドはペアになります。このパターンは通常、行 1 にヘッダーがあり、各列の名前が続き、その後に変数の数が続く CSV タイプファイルに適しています。各列にデータがある行。
これは不正行為を含む順序も維持します。詐欺を取り除き、秩序を維持するには:
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を学ぶようですので、説明する方法を使用して行う方法は次のとおりです。まず、私は,
分離を使用しません。同様の作業を行うために線を使用する方が簡単です。その後、NR
特殊変数を使用してFNR
両方のファイルをリンクできます。NR
現在の入力ライン番号を保存し、FNR
入力ライン番号を保存します。現在読んでいるファイルの。したがってawk
、それぞれ2行の2つのファイルが与えられた場合、ファイルはNR
fromに移動します1
が、4
2番目のファイルの最初の行を読み取るときはFNR
fromに移動してから再び移動1
します2
。1
2
それらを組み合わせると、次のようになります。
## 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()
-文字を10進数に変換する関数
printf "%x", ord($i)
-10進数を16進数に変換
また: chr()
-10進数を文字に変換
答え4
自分で書くのではなく、既存のプログラムを使うのはどうですか?私はお勧めしますascii
エリックS.レイモンドから。
上記のコマンドを使用してASCII文字の16進値を出力するには、次のコマンドを実行します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