文字コードとか考えてません。最初 gawk で書いてたけど match() でマッチした文字列を配列で受け取れるgawk拡張について
3.1.5 はバグ持ちだよ
という記述を見つけてしまって凹んでました。というか手元の 3.1.4 で試して動いたんだか動かないんだかよく分からなくて放り投げてしまいました。awk スクリプトで最新版を要求するなんて優しさが足りない。
Therefore use:
echo test4325363test | gawk 'match($0, "([^0-9]*)([0-9]+)(.*)", a) { print a[2] }'
to extract the number.
Please, note that gawk 3.1.5 has some bugs in the match function. These should be corrected in gawk 3.1.6 (see ftp://ftp.gnu.org).
How to gram awk's regexp submatches? - Object Mix
というわけで Ruby に鞍替え。
なんか諸々 CSV に決め打ちで TSV とか対応できませんけど勘弁してちょ。optparse で delimiter 受け取って動的に正規表現作ればイケますよ、とだけ書いてお茶を濁しておく。
途中、範囲式からループを回す処理は見慣れないと気持ち悪いけど、なぜか Ruby を書いていると i += 1 とかカウンタを自分でいじる方が気持ち悪いと感じるようになるのです。for ( ; ; ) 文がないので while の中で自分でカウンタいじることになるんだけど、そうするとインクリメントのタイミングによって値が変わっちゃうとかそういう落とし穴を作ることになるんでやりたくなくなるのです。do end と { } が混ざっているのはごめんなさいということで。
#! /usr/bin/env ruby
class Csv2Fixed
def initialize
@num_fields = 0
@num_lines = 0
@len_cols = []
@buf = []
end
def run
while ( line = gets )
arr = split_csv( line.chomp )
if ( arr.size > @num_fields )
@num_fields = arr.size
end
store_line( arr )
@num_lines += 1
end
output()
end
def store_line( arr )
@buf[@num_lines] = []
(0 ... arr.size).each do |i|
str = arr[i]
if ( @len_cols[i].nil? or str.size > @len_cols[i] )
@len_cols[i] = str.size
end
@buf[@num_lines].push( str )
end
end
def output
(0 ... @num_lines).each do |i|
arr = @buf[i]
(0 ... arr.size).each do |j|
printf( "%-*s ", @len_cols[j], @buf[i][j] )
end
printf( "\n" )
end
end
def split_csv( str )
str = str + ","
arr = []
str.scan( /(\"(?:[^\"]|\"\")*\"|[^,]*),/ ).each { |e|
arr.push( e.to_s.sub( /^"/, '' ).sub( /"$/, '' ).sub( /""/, '"' ) )
}
return arr
end
end # of class Csv2Fixed
if ( __FILE__ == $0 )
app = Csv2Fixed.new()
app.run()
end