■ASCIIコードの順序の性質と8進数エスケープの関係を整理してみる。 以下でASCIIコード表の8進数を一覧した。 これを使って、検索パターンが意図した文字にマッチするかを確認する。 awkで記号をエスケープしたいときに使う、文字と8進数の一覧 http://labunix.hateblo.jp/entry/20180801/1533056689 ■行処理(改行)から列処理(スペース)に変える。 後々面倒なので、ブレース展開に書き換える。 $ echo "`seq 32 126`" | awk '{printf "%c,\\%03o\n",$1,$1}' > 1.txt $ echo `seq 32 126` | awk '{for(a=1;a<=NF;a++)printf "%c,\\%03o\n",$a,$a}' > 2.txt $ echo {32..126} | awk '{for(a=1;a<=NF;a++){printf "%c,\\%03o\n",$a,$a}}' > 3.txt $ md5sum [123].txt 152fa2b7df00c063702f07aebcb948de 1.txt 152fa2b7df00c063702f07aebcb948de 2.txt 152fa2b7df00c063702f07aebcb948de 3.txt ■awkだとかえって列処理用に文字数が増えるので、シェル用に書き換える。 8進数の表示も止めて、余分なスペースも改行も無くなった。 $ printf "$(printf '\\%03o' {32..126})";echo !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ■ところで、0..127でなく、32..126にした理由としては、ASCIIコード自体は、0..127まで割り当てられている。 $ echo "$(printf '\\%03o' {0..127})" | sed 's/.\{,60\}/\n&/g' \000\001\002\003\004\005\006\007\010\011\012\013\014\015\016 \017\020\021\022\023\024\025\026\027\030\031\032\033\034\035 \036\037\040\041\042\043\044\045\046\047\050\051\052\053\054 \055\056\057\060\061\062\063\064\065\066\067\070\071\072\073 \074\075\076\077\100\101\102\103\104\105\106\107\110\111\112 \113\114\115\116\117\120\121\122\123\124\125\126\127\130\131 \132\133\134\135\136\137\140\141\142\143\144\145\146\147\150 \151\152\153\154\155\156\157\160\161\162\163\164\165\166\167 \170\171\172\173\174\175\176\177 ■上記をcolのフィルタに通すと、32..126と最後の改行となる。 $ man col | awk '/コントロール文字/&&/エスケープ/' col が認識できないコントロール文字およびエスケープシーケンスは削除される。 $ printf "$(printf '\\%03o' {0..127})" | col | od -t d1 -t c 0000000 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 ! " # $ % & ' ( ) * + , - . / 0000020 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 0000040 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 @ A B C D E F G H I J K L M N O 0000060 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 P Q R S T U V W X Y Z [ \ ] ^ _ 0000100 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ` a b c d e f g h i j k l m n o 0000120 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 10 p q r s t u v w x y z { | } ~ \n 0000140 ■制御文字やエスケープ文字を表示してみる。 10番目の「nl」は「\n」 $ printf "$(printf '\\%03o' {0..127})" | od -t d1 -t a 0000000 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 nul soh stx etx eot enq ack bel bs ht nl vt ff cr so si 0000020 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 dle dc1 dc2 dc3 dc4 nak syn etb can em sub esc fs gs rs us 0000040 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 sp ! " # $ % & ' ( ) * + , - . / 0000060 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 0000100 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 @ A B C D E F G H I J K L M N O 0000120 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 P Q R S T U V W X Y Z [ \ ] ^ _ 0000140 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 ` a b c d e f g h i j k l m n o 0000160 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 p q r s t u v w x y z { | } ~ del 0000200 ■制御文字やエスケープ文字を表示する方法は他にもあって、 例えばcatにも可視化のオプションがある。 10文字目で改行されているのは「nl」のため。 行の終わりには「$」が付く。 最後は改行で終わっていないので、行の終わりを示す「$」が無い。 $ printf "$(printf '\\%03o' {0..127})" | sed -e 's/[Aa]/\n&/g' | cat -A;echo ^@^A^B^C^D^E^F^G^H^I$ ^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^]^^^_ !"#$%&'()*+,-./0123456789:;<=>?@$ ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`$ abcdefghijklmnopqrstuvwxyz{|}~^? ■ROT13 単換字式暗号。またはシーザー暗号の一つ。 52文字の半分は26文字は大文字小文字。 大文字小文字を同一視してその半分は13文字。 $ echo $((52 / 2));echo $((26 / 2)) 26 13 $ printf "$(printf '\\%03o\n' {32..126})" | \ awk '/[A-Za-z]/{print "echo -n \042"$1" \042;echo "$1" | tr \047A-Za-z\047 \047N-ZA-Mn-za-m\047"}' | sh | nl | column -c 40 1 A N 27 a n 2 B O 28 b o 3 C P 29 c p 4 D Q 30 d q 5 E R 31 e r 6 F S 32 f s 7 G T 33 g t 8 H U 34 h u 9 I V 35 i v 10 J W 36 j w 11 K X 37 k x 12 L Y 38 l y 13 M Z 39 m z 14 N A 40 n a 15 O B 41 o b 16 P C 42 p c 17 Q D 43 q d 18 R E 44 r e 19 S F 45 s f 20 T G 46 t g 21 U H 47 u h 22 V I 48 v i 23 W J 49 w j 24 X K 50 x k 25 Y L 51 y l 26 Z M 52 z m ■ROTATE47は区切り文字のspを除き、94文字を使用する。 エスケープしないと使えないものばかりなので、 ほとんど実装されないのも頷ける。 $ echo $((94 / 2)) 47 $ printf "$(printf '\\%03o\n' {33..126})" | nl | column -c 120 1 ! 15 / 29 = 43 K 57 Y 71 g 85 u 2 " 16 0 30 > 44 L 58 Z 72 h 86 v 3 # 17 1 31 ? 45 M 59 [ 73 i 87 w 4 $ 18 2 32 @ 46 N 60 \ 74 j 88 x 5 % 19 3 33 A 47 O 61 ] 75 k 89 y 6 & 20 4 34 B 48 P 62 ^ 76 l 90 z 7 ' 21 5 35 C 49 Q 63 _ 77 m 91 { 8 ( 22 6 36 D 50 R 64 ` 78 n 92 | 9 ) 23 7 37 E 51 S 65 a 79 o 93 } 10 * 24 8 38 F 52 T 66 b 80 p 94 ~ 11 + 25 9 39 G 53 U 67 c 81 q 12 , 26 : 40 H 54 V 68 d 82 r 13 - 27 ; 41 I 55 W 69 e 83 s 14 . 28 < 42 J 56 X 70 f 84 t ■ところで、大文字小文字を検索する[A-Za-z]を[A-z]としてはいけない理由もASCIIコードの文字順にある。 $ printf "$(printf '\\%03o\n' {32..126})" | awk '/[A-z]/&&!/[A-Za-z]/' | tr -d '\n' | od -t o1 -t a 0000000 133 134 135 136 137 140 [ \ ] ^ _ ` 0000006 ■SCIIコード表から見て連続していない。 $ printf "$(printf '\\%03o' {65..90})$(printf '\\%03o' {97..122})" | od -t d1 -t a 0000000 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 A B C D E F G H I J K L M N O P 0000020 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 Q R S T U V W X Y Z a b c d e f 0000040 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 g h i j k l m n o p q r s t u v 0000060 119 120 121 122 w x y z 0000064 ■上記を短く書いてもその本質は変わらない。 $ printf "$(printf '\\%03o' {65..90} {97..122})" | od -t d1 -t a 0000000 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 A B C D E F G H I J K L M N O P 0000020 81 82 83 84 85 86 87 88 89 90 97 98 99 100 101 102 Q R S T U V W X Y Z a b c d e f 0000040 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 g h i j k l m n o p q r s t u v 0000060 119 120 121 122 w x y z 0000064 ■[A-z]にしてしまいそうな人のために、awkでは[:alpha:]がある。 $ printf "$(printf '\\%03o\n' {32..126})" | awk '/[[:alpha:]]/' | tr -d '\n' | od -t o1 -t c 0000000 101 102 103 104 105 106 107 110 111 112 113 114 115 116 117 120 A B C D E F G H I J K L M N O P 0000020 121 122 123 124 125 126 127 130 131 132 141 142 143 144 145 146 Q R S T U V W X Y Z a b c d e f 0000040 147 150 151 152 153 154 155 156 157 160 161 162 163 164 165 166 g h i j k l m n o p q r s t u v 0000060 167 170 171 172 w x y z 0000064 ■同じ理由で[0-z]と書いても意図した検索は出来ない。 「{58..64}」の記号が追加で混入してしまう。 「{91..96}」の記号の出現頻度が低くて見逃されがちだとしても、原因は同じなので注意する。 $ printf "$(printf '\\%03o\n' {32..126})" | awk '/[0-z]/&&!/[[:alnum:]]/' | tr -d '\n' | od -t d1 -t c 0000000 58 59 60 61 62 63 64 91 92 93 94 95 96 : ; < = > ? @ [ \ ] ^ _ ` 0000015 ■逆にsp(スペース)を除きエスケープするべき文字列を、 awkだけでなくよく使われる8進数エスケープ用に一覧すると、以下のようになる。 $ printf "$(printf '\\%03o\n' {32..126})" | awk '!/[[:alnum:]]| /' | tr -d '\n' | od -t o1 -t c 0000000 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 072 ! " # $ % & ' ( ) * + , - . / : 0000020 073 074 075 076 077 100 133 134 135 136 137 140 173 174 175 176 ; < = > ? @ [ \ ] ^ _ ` { | } ~ 0000040 ■10進数では{33..47} {58..64} {91..96} {123..126}となる。 $ printf "$(printf '\\%03o' {33..47} {58..64} {91..96} {123..126})" | od -t d1 -t c 0000000 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 58 ! " # $ % & ' ( ) * + , - . / : 0000020 59 60 61 62 63 64 91 92 93 94 95 96 123 124 125 126 ; < = > ? @ [ \ ] ^ _ ` { | } ~ 0000040 ■一部ならともかく、全部覚えていられないよ。 ということでググれない環境でエスケープ文字探すときには、 以下か、その派生シェル芸をすれば良い。 $ printf "$(printf '\\%03o' {0..127})" | col | awk '!/[[:alnum:]]| /' | od -t o1 -t c 0000000 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 072 ! " # $ % & ' ( ) * + , - . / : 0000020 073 074 075 076 077 100 133 134 135 136 137 140 173 174 175 176 ; < = > ? @ [ \ ] ^ _ ` { | } ~ 0000040 ■派生シェル芸の例 $ echo {33..126} | awk '{for(a=1;a<=NF;a++)printf "%c\n",$a}' | awk '!/[[:alnum:]]| /' | tr -d '\n' | od -t o1 -t a 0000000 041 042 043 044 045 046 047 050 051 052 053 054 055 056 057 072 ! " # $ % & ' ( ) * + , - . / : 0000020 073 074 075 076 077 100 133 134 135 136 137 140 173 174 175 176 ; < = > ? @ [ \ ] ^ _ ` { | } ~ 0000040 $ echo {33..126} | awk '{for(a=1;a<=NF;a++)printf "%c,\\%03o\n",$a,$a}' | awk -F\, '$1 !~ /[[:alnum:]]| /' | column -c 120 !,\041 $,\044 ',\047 *,\052 -,\055 :,\072 =,\075 @,\100 ],\135 `,\140 },\175 ",\042 %,\045 (,\050 +,\053 .,\056 ;,\073 >,\076 [,\133 ^,\136 {,\173 ~,\176 #,\043 &,\046 ),\051 ,,\054 /,\057 <,\074 ?,\077 \,\134 _,\137 |,\174