カテゴリ:コマンドラインツール
#!/usr/local/bin/ruby
def help print <<-HELP_END mkwild mkwild [-1] [field1 field2 ...] オプション -1 最初のワイルドカードだけにする 説明 mkwild は、bash のパス名展開の [] とほとんど逆の操作(集約)を行います。 パス名展開では、例えば aa[abc] --> aaa aab aac という展開が行われますが、mkwild はこれとほとんど逆の操作(集約) aaa aab aac --> aa[abc] を行います。 オプション以外の引数が与えられた場合は、引数1個ずつをレコードとします。 オプション以外の引数がない場合、標準入力からレコードを取り込みます。 レコードの最初のフィールドとそれに続く区切り記号を除いた部分が全く同じ 文字列で、最初のフィールドが1文字違いのときに集約が行われます。 例をあげれば aaa --> aa[ab] --+--> a[ab][ab] aab | aba --> ab[ab] --+ abb となります。(例は最初のフィールドだけ表示しています) ホワイトスペースだけのレコードがあれば消去されます。 オプション -1 は、集約を1段階だけ(前述の例で左から2番目のコラムまで)で 中断します。デフォルトでは、可能なかぎり繰り返します。 入力レコードの順番が、集約結果に影響する場合があります。 集約結果は、ソートされずに、入力の出現順番に出力されます。 [] の中の文字はソートされません。出現順番です。 [] の中の文字は重複は残されませんので、入力に全く同じレコードがいくつ あっても、1個のときと出力は変わりません。 mkwild の行う集約は、パス名展開の「ほとんど」逆の操作ですが、次の点が 異なります。 1. bash のパス名展開は、* や ? の展開を行いますが、集約には関係ありません。 また、パス名展開で使うことのできる、文字クラスや - による文字の範囲での 指定は、集約には関係ありません。 2. bash のパス名展開は、ファイルが存在する場合だけ展開しますが、 集約は、ファイルの存在には関係ありません。 集約された [] の中には、入力に存在するものだけ含んでいます。 ファイルの存在と関係がないため、ファイル名以外の用途で使う事も可能です。 バグ 入力レコードの順番が、集約結果に影響する場合がありますが、異なる集約結果を 得るためには、mkwild の内部動作を考えて、入力を変更するしか方法がありません。 入力が sort されている場合、集約結果は人間にとって分かりやすい物であると 思います。 フィールドの区切り記号は、空白文字(ruby の \\s で [ \\t\\n\\r\\f])です。 例えば grep は、ファイル名を出力する場合のファイル名とマッチの出力の区切り 記号は ':' ですが、これと mkwild のフィールド区切り記号の整合が取れていません。 HELP_END end opt=Hash.new ARGV.delete_if {|x| case x when "-1" then opt[x]=true when "-h","--help" then help;exit end} if ($*.size==0) data=$stdin.readlines else data=$* end data.uniq!; data.each {|i| i.chomp!}; data.delete_if {|a| a=~/^\s*$/} #最初のレコードとそれ以降を切り分けて Arrayにする data=data.collect {|a| /^\s*([^\s]*)\s*(.*)/.match(a).to_a.values_at(1,2)} data_size=0; begin data=data.inject([]) {|r,aa| a=aa[0]; j=0; wild=nil; ri=(0...r.size).find {|ri| if (aa[1]==r[ri][1]) b=r[ri][0]; i=j=0; wild=nil until (i>=a.size || j>=b.size) if (a[i]==b[j]) ;then i+=1;j+=1 elsif (wild) ;then j=b.size+1; wild=nil ##2個以上異なる elsif (b[j]!=?[);then wild=[j,"["+b[j].chr+a[i].chr+"]"];i+=1;j+=1 ## make [] elsif (c=b.index(/\]/,j));then ## add to [] wild=[j..c,b[j...c]+(b[j..c].include?(a[i])?"":a[i].chr)+"]"]; i+=1;j=c+1 else j=b.size+1 ## [] が対応していない 通常の文字として処理 end;end ## until wild && i==a.size && j==b.size; end} if (ri) r[ri][0][wild[0]]=wild[1]; else r.push(aa) end r } end while (!opt["-1"] && data_size!=(data_size=data.size)) s=data.collect {|a| a[0].size}.max data.collect {|a| (a[1].size==0)?a[0]:sprintf("%-*s %s",s,a[0],a[1])}.each {|a| (a+"\n").display} # end of mkwild
最終更新日
2007年09月25日 09時54分07秒
|