#!/usr/bin/env ruby ################################################## #= gpedit #== SYNOPSIS SYNOPSIS = <<-"SYNOP" Create or overwrite the attributes of a variable specified by a gtool4-type URL (Only netCDF files are supported). SYNOP #== HISTORY # # 2007/07/18 Y. Morikawa 'gpattr' is renamed to 'gpedit' # 2006/09/29 Y. Morikawa A value looks like numeric is treated as a numerical value # 2005/01/09 Y. Morikawa # 2005/01/07 D. Tsukahara # #==USAGE URLFMT = "path@[varname:var_attr=...][varname|+global_attr]" USAGE = " % #{File.basename(__FILE__)} [options] url where the format of the url is #{URLFMT} " #==EXAMPLES EXAMPLES = " * Add % #{File.basename(__FILE__)} data.nc@temp:units=W/m % #{File.basename(__FILE__)} -a data.nc@temp:missing_value=-2.0e20 % #{File.basename(__FILE__)} --add data.nc@temp+title=\"surface temperature\" * Delete % #{File.basename(__FILE__)} -d data.nc@lon:topology % #{File.basename(__FILE__)} --delete data.nc@lon+Conventions " # ################################################## require "optparse" require "numru/netcdf" include NumRu opt = OptionParser.new OPTS = {} ARGV.options{|opt| opt.summary_width = 23 opt.summary_indent = ' '*6 opt.on( '-a', '--add', "Add attribute (default)." ){|v| OPTS[:add] = v} opt.on( '-d', '--delete', "Delete attribute." ){|v| OPTS[:delete] = v} opt.on_tail('-h', '-H', '--help', "Show this help message.\n" ){|v| OPTS[:help] = v} opt.parse! } ## help def help(opt) print <<-"EOF" #{File.basename(__FILE__)}: #{SYNOPSIS} USAGE: #{USAGE} OPTION: \n#{opt.to_a[1..-1].join("")} EXAMPLES: #{EXAMPLES} EOF end private :help ##################################################### def to_appropriate_type(str) if str =~ /\.|e/i val = str.to_f else val = str.to_i end if val.to_i == 0 unless str =~ /^0+((\.0+)?(e\d+)?)?$/i val = str end end return val end def url_error(msg) $stderr.print <<-"EOF" Error: invalid URL: #{msg}. Current URL format is #{URLFMT} EOF exit 1 end def parse_gturl_for_attr(gturl) if /(.*)@(.*)/ =~ gturl file = $1 var = $2 else url_error "'@' between path & variable is not found" end if /(.*):(.*)/ =~ var var_name = var.split(":")[0] att = var.split(":")[1] if /(.*)\=(.*)/ =~ att var_att = att.split("=")[0] global_att = nil att_val = to_appropriate_type(var.split("=")[1]) elsif OPTS[:delete] var_att = att global_att = nil att_val = nil else url_error "'=' between atribute name & value is not found" end elsif /(.*)\+(.*)/ =~ var var_name = var.split("+")[0] att = var.split("+")[1] if /(.*)\=(.*)/ =~ att var_att = nil global_att = att.split("=")[0] att_val = to_appropriate_type(att.split("=")[1]) elsif OPTS[:delete] var_att = nil global_att = att att_val = nil else url_error "'=' between atribute name & value is not found" end else url_error "':' or '+' between atribute name & value is not found" end if !(att_val) && !OPTS[:delete] url_error "attribute value is not found. you must point out unless delete attribute" end [file, var_name, var_att, global_att, att_val] end ##################################################### if OPTS[:help] || ARGV.length != 1 then help(opt) exit end gturl = ARGV[0] file, var, var_att, global_att, att_val = parse_gturl_for_attr(gturl) begin nc = NetCDF.new(file, "r") nc.close rescue NetcdfSyserr $stderr.print " Error: " + file + ": " + $!.to_s + "\n" exit 1 rescue NetcdfNotnc $stderr.print " Error: " + file + ": " + $!.to_s + "\n" $stderr.print " \"#{File.basename(__FILE__)}\" supports only netCDF files.\n" exit 1 end nc = NetCDF.new(file, "a+") if nc.var(var) var = nc.var(var) elsif nc.dim(var) var = nc.dim(var) end nc.redef if var.class.to_s == "String" $stderr.print " Error: #{file}@#{var}: variable is not found.\n" exit 1 end if OPTS[:delete] begin nc.att(global_att).delete if global_att var.att(var_att).delete if var_att rescue NoMethodError print " Warning: " + gturl + " is not exist.\n" end else nc.put_att(global_att, att_val) if global_att var.put_att(var_att, att_val) if var_att end nc.close