12
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

URLエンコード・デコードする

Webサーバーログ解析で使いたかった

Webサーバーのログを見ていると、検索ページからジャンプしてきている形跡があった。しかし、検索キーワードはURLエンコードされた状態であり、デコードしないとわからない。果たしてどんなキーワードなのか興味があった。

そこで、FreeBSDのportsに収録されているurlendecというプログラムをサクっとインストールしようとしたら……

32ビット専用だった
# cd /usr/ports/net/urlendec
# make install
===>  urlendec-1.0 is only for i386, while you are running amd64.
*** [install] Error code 1

Stop in /usr/ports/net/urlendec.
# 

これだから、POSIX準拠でないコマンドは信用ならんのじゃ!!!

しょーがないのでデコーダーを自作した

というわけでPOSIX原理主義全開で作った。UNIXならどこでも動くはずなので公開する。必要な方はコピペして使うといい。

urldecode
#! /bin/sh

case $# in
  0) cat -                   ;;
  *) for file in "$@"; do
       case "$file" in
         -)  :             ;;
         /*) :             ;;
         *)  file="./$file";;
       esac
       cat "$file"
     done                    ;;
esac |
exec env - awk '
BEGIN {
  # --- prepare
  LF  = sprintf("\n");
  OFS = "";
  ORS = "";
  # --- prepare decoding
  for (i=0; i<256; i++) {
    l  = sprintf("%c",i);
    k1 = sprintf("%02x",i);
    k2 = substr(k1,1,1) toupper(substr(k1,2,1));
    k3 = toupper(substr(k1,1,1)) substr(k1,2,1);
    k4 = toupper(k1);
    p2c[k1]=l;p2c[k2]=l;p2c[k3]=l;p2c[k4]=l;
  }
  # --- decode
  while (getline line) {
    gsub(/\+/, " ", line);
    while (length(line)) {
      if (match(line,/%[0-9A-Fa-f][0-9A-Fa-f]/)) {
        print substr(line,1,RSTART-1), p2c[substr(line,RSTART+1,2)];
        line = substr(line,RSTART+RLENGTH);
      } else {
        print line;
        break;
      }
    }
    print LF;
  }
}'

GNU版のsedを使えば簡単に書けるのは知っているけど、せっかく作るなら可搬性を高めたいのでPOSIXの範囲で作った。結局AWKにベッタリで、しかも全てをBEGINセクションで済ませるというAWKっぽくない使い方だけど、今回の目的では意味を成さないフィールド分割処理($0,$1,$2,……を作る)が走らないようにするため。

使い方

オリジナルのurldecodeのような各種オプションには対応していないが、変換したいテキストデータを標準入力あるいはファイル(引数で指定)で与えるだけ。簡単でしょ。

ついでにエンコーダーも作った

urlencode
#! /bin/sh

case $# in
  0) cat -                   ;;
  *) for file in "$@"; do
       case "$file" in
         -)  :             ;;
         /*) :             ;;
         *)  file="./$file";;
       esac
       cat "$file"
     done                    ;;
esac |
exec env - awk '
BEGIN {
  # --- prepare
  LF = sprintf("\n");
  OFS = "";
  ORS = "";
  # --- prepare encoding
  for(i= 0;i<256;i++){c2p[sprintf("%c",i)]=sprintf("%%%02X",i);}
  c2p[" "]="+";
  for(i=48;i< 58;i++){c2p[sprintf("%c",i)]=sprintf("%c",i);    }
  for(i=65;i< 91;i++){c2p[sprintf("%c",i)]=sprintf("%c",i);    }
  for(i=97;i<123;i++){c2p[sprintf("%c",i)]=sprintf("%c",i);    }
  c2p["-"]="-"; c2p["."]="."; c2p["_"]="_"; c2p["~"]="~";
  # --- encode
  while (getline line) {
    for (i=1; i<=length(line); i++) {
      print c2p[substr(line,i,1)];
    }
    print LF;
  }
}'

エンコードする必要のない文字(英数字や一部の記号)はそのまま流すようにしてある。

尚、データの与え方はデコーダーと同じ。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
12
Help us understand the problem. What are the problem?