awk で数字を取り出す

すげーコード見つけたからなのですが、同じ処理を awk でやってみるとどうやれば良いかというものです。 数字を取り出す基準などでも Python や Ruby については語られていますが、awk でも処理できます。

前半部分は数字だけを抜き出すものです。 一方、後半部分は数字と数字以外を両方分割して取り出すものです。

#! /usr/bin/gawk -f
# digits_split.awk
# Ref: http://d.hatena.ne.jp/odz/20080708/1215470530
# Ref: http://www.kt.rim.or.jp/~kbk/zakkicho/08/zakkicho0807a.html#D20080707-5
# Ref: http://d.hatena.ne.jp/s-n-k/20080630/1214836026

BEGIN {
    str = "abc123a4bcd56";
    #str = "123a4bcd56";

    # 数字だけ抜き出して配列に格納
    num_str = split(str, arr_str, /[^[:digit:]]+/);
    for (i = 1; i <= num_str; i++) {
        print arr_str[i];
    }
    delete arr_str;
    i = 0;

    print "============================================================";
    # 文字と数字を分離して配列に格納
    while (length(str) > 0) {
        match(str, /[[:digit:]]+/);
        arr_str[++i] = substr(str, 1, RSTART - 1);      # 文字
        arr_str[++i] = substr(str, RSTART, RLENGTH);    # 数字
        str = substr(str, RSTART + RLENGTH);
    }
    for (j = 1; j <= i; j++) {
        print arr_str[j];
    }
}

実行してみます。

$ gawk -f digits_split.awk

123
4
56
============================================================
abc
123
a
4
bcd
56

もう少しスマートな方法もありそうですが、前者は数字以外を split() 関数のセパレータにしたもので、後者が match() 関数の RSTART と RLENGTH を用いたものです。(少し後者は破壊的ですが・・・)

tag_gawk.pngtag_gawk.png