- 浏览: 44359 次
- 性别:
- 来自: 杭州
文章分类
最新评论
Perl解释Properties不太方便,需要自己分析
Ruby也没有提供现成的库,自己写了一个,可以看出,ruby跟perl是何等的相似,尤其是正则表达式的应用这块,难怪网络上都说ruby是perl6,确实不假。
其实还写了一版python的,也一并贴上来对比一下
#!/usr/bin/perl -w package ncs::Properties; use vars qw(@ISA @EXPORT @EXPORT_OK); use Exporter; @ISA = qw(Exporter); @EXPORT = qw(load get set merge merge_with_file); use ncs::Common; sub new { my $this = {}; $this->{'properties_file'} = 'ncs_default.properties'; $this->{'properties'} = {}; bless $this; return $this; } sub load { my ($class, $properties_file, $keep_escape) = @_; if (!defined($properties_file) || $properties_file eq ""){ $properties_file = "ncs.properties"; } $class->{'properties_file'} = $properties_file; my $k = $v = ""; my $is_multiline = 0; open(PROPFILE, "<$properties_file") || die("Cannot open properties file $properties_file"); while($line = <PROPFILE>){ $line = trim($line); #space line or commentted line will be ignored if($line =~ /^$/ || $line =~ /^#/){ next; } if($line =~ /\\$/){ #end with \ $line =~ s/\\$//; if($is_multiline){ #not first line,not end line $v = $v.' '.$line; } else{ #first line ($k,$v) = split("=", $line, 2); $is_multiline = 1; } next; } if($is_multiline){ #print "is multiline: $is_multiline\n"; #print "$line\n"; $v = $v.' '.$line; if($line =~ /[^\\]$/){ #end line $class->{'properties'}->{trim($k)} = trim($v); #print "$k=$v\n"; $k = $v = ""; $is_multiline = 0; } next; } ($k,$v) = split("=", $line, 2); if(trim($k) eq ""){ next; } #print("$k=$v"); $class->{'properties'}->{trim($k)} = trim($v); $k = $v = ""; } close(PROPFILE); my $import = $class->get("ncs.import"); $import = $class->unescapeProperty("ncs.import", $import) if $import; if(-e $import){ print("found import properties: $import\n"); $class->merge_with_file($import); } $class->unescapeProperties() if !$keep_escape; return $class->{'properties'}; } sub unescapeProperty { my ($class, $k, $v) = @_; if(!defined($v) || $v =~ /^\s*$/){ return; } while($v =~ /^(.*)\${([^}]+)}(.*)$/){ #match ${ncs.log.dir} my $prefix = (defined($1) ? $1 : ""); my $matched = $2; my $suffix = (defined($3) ? $3 : ""); #print("matched key: $matched\n"); if(!exists($class->{'properties'}->{$matched})){ warn("[warn] matched key not exists: $matched"); last; } #matched key exits #print("$matched=".$class->{'properties'}->{$matched}."\n"); $class->{'properties'}->{$k} = $prefix.$class->{'properties'}->{$matched}.$suffix; $v = $class->{'properties'}->{$k}; } while($v =~ /^(.*)(\$ENV{[^}]+})(.*)$/){ #match $ENV{HOME} my $prefix = (defined($1) ? $1 : ""); my $matched = $2; my $suffix = (defined($3) ? $3 : ""); #print("matched env: $matched\n"); $matched = eval($matched) || ''; #print("matched env value:".$matched."\n"); $matched = (defined($matched) ? $matched : ""); $class->{'properties'}{$k} = $prefix.$matched.$suffix; $v = $class->{'properties'}->{$k}; } #print("$k=$class->{'properties'}->{$k}\n"); return $v; } sub unescapeProperties { my $class = shift @_; my $props = $class->{'properties'}; #print "list properties before unescape start\n"; while( local ($k,$v) = each(%$props)){ #print("$k=$v\n"); $class->unescapeProperty($k, $v); } #print "list properties before unescape end\n"; } sub get { my ($class,$key,$default) = @_; if(exists($class->{'properties'}->{$key})){ return $class->{'properties'}->{$key}; } if(defined($default)){ #not exists $props{$key} return $default; } return ""; #no default } sub set { my ($class, $key, $value) = @_; $class->{'properties'}->{$key} = $value; } sub merge { my ($class, $props_to_be_merged, $override) = @_; my $props = $class->{'properties'}; while(local ($k,$v) = each(%$props_to_be_merged)){ $k = trim($k); if($k eq ""){ next; } if(exists($props->{$k})){ next if(!$override); } $props->{$k} = trim($v); } return $props; } sub merge_with_file { my ($class, $file_to_be_merged, $override) = @_; if(-e $file_to_be_merged){ return $class->merge(ncs::Properties->new()->load($file_to_be_merged, 1), $override); } return $class->{'properties'}; }
Ruby也没有提供现成的库,自己写了一个,可以看出,ruby跟perl是何等的相似,尤其是正则表达式的应用这块,难怪网络上都说ruby是perl6,确实不假。
#!/usr/bin/ruby -w class Properties def initialize @properties = {} end def load(properties_file, escape=true) raise "#{properties_file} not exists!" if not File.exists?(properties_file) @properties_file = properties_file k = v = "" is_multiline = false IO::foreach(@properties_file) {|line| line = line.strip #skip blank-space line or comments next if line =~/^\s*$/ or line =~/^\s*#/ #puts "line: #{line}" #end with \ if line =~ /\\$/ #puts "line end with \\: #{line}" line.chomp!().chop!() if is_multiline #not first line,not end line v = v + ' ' + line else #first line k,v=line.split(/=/, 2) is_multiline = true end next; end if is_multiline #puts "line is one of multiline: #{is_multiline}" v = v+' '+line if line =~ /[^\\]$/ #end line @properties.store(k.strip, v.strip) #puts "#{k}=#{v}" k = v = "" is_multiline = false end next; end k,v=line.split(/=/, 2) next if(k.strip.empty?) #puts "#{k}=#{v}" @properties.store(k.strip, v.strip) k = v = "" } self.import_files() self._escapeprops() if escape return self end def _escapeprops @properties.each do |key,val| self._escapeprop(key,val) end end def _escapeenv(env) env = env.delete('$').sub('{','["').sub('}','"]') #puts "env: #{matched}" (eval(env) or "") end def _escapeprop(key,val) return if val =~ /^\s*$/ #ignore empty value while val =~ /^(.*)\$\{([^}]+)\}(.*)$/ #match ${ncs.log.dir} prefix = $1 or ""; matched = $2; suffix = $3 or "" #puts "matched key: #{matched}" if not @properties.key?(matched) puts "matched key not exists: #{matched}" break end #matched key exits #puts "#{matched}="+ @properties.fetch(matched) @properties.store(key, prefix+@properties.fetch(matched)+suffix) val = @properties.fetch(key) end while(val =~ /^(.*)(\$ENV\{[^}]+\})(.*)$/) #match $ENV{HOME} prefix = $1 or ""; matched = $2; suffix = $3 or "" matched = self._escapeenv(matched) #puts "matched env value:#{matched}" #puts "prefix=#{prefix}, matched=#{matched}, suffix=#{suffix}" @properties.store(key, prefix+matched+suffix) val = @properties.fetch(key) end #puts "#{key}=#{@properties[key]}" return val; end def get(key, default='') if(@properties.key?(key)): return @properties.fetch(key) end if(!default.nil?): return default end end def getint(key, default=0) self.get(key,default).to_i end def getfloat(key, default=0.0) self.get(key,default).to_f end alias getlong getint alias getdouble getfloat def getboolean(key) return true if self.getint(key, 0) > 0 return false end def set(key,value) @properties.store(key,value) end def size @properties.size end def merge(props_to_be_merged, override=false) props_to_be_merged.each do |k,v| next if k.strip.empty? next if @properties.key?(k) and !override @properties.store(k, v.strip) end self end def import_files(override=false) import = self.get("ncs.import") if defined?(import) and not import.empty? puts "found import properties: #{import}" import = self._escapeprop("ncs.import",import) if not import.nil? and File.exist?(import) return self.merge(Properties.new.load(import,false).to_hash, override) end end self end def to_hash @properties end def keys @properties.keys end def values @properties.values end def dump keys = @properties.keys.sort keys.each do |key| val = self.get(key) puts "#{key}=#{val}" end end protected :_escapeprop,:_escapeenv,:_escapeprops end
其实还写了一版python的,也一并贴上来对比一下
#!/usr/bin/env python from ncs.core.component import Component from ncs.exceptions import * import sys import os import re import logging class PropertiesNotExist(Exception): def __init__(self, properties_file): self.properties_file = properties_file def __str__(self): return repr("properties file {0} not exist!".format(self.properties_file)) class PropertiesNotLoad(Exception): def __init__(self, properties_file): self.properties_file = properties_file def __str__(self): return repr("properties file {0} is not loaded!".format(self.properties_file)) class Properties(Component): """ This is a python portion for java Properties file """ def __init__(self): Component.__init__(self, 'ncs.core.properties.Properties', ['load','get','set','search']) self.properties_file = '' self.raw_properties = {} self.properties = {} self.logger = logging.getLogger(self.__class__.__name__) def load(self, resource): if not os.path.exists(resource): self.logger.error("{0} not exists".format(resource)) raise PropertiesNotExist(resource) if not os.path.isfile(resource): self.logger.error("{0} is not a file!".format(resource)) raise PropertiesNotLoad(resource) self.properties_file = resource self.raw_properties = self.properties = self._parse(resource) #check if there is import properties or file import_file = self.get("ncs.import", self.get("import")) if import_file: import_file = self._unescape_property(import_file) if not os.path.exists(import_file): self.logger.warn("import file {0} not exists".format(import_file)) self.logger.warn("ignored import file {0}".format(import_file)) if self.isdebugon(): print("import properties file: {0}".format(import_file)) self.import_from_file(import_file) self._unescape_properties() return self.properties def _parse(self, resource): props = dict() fp = open(resource, 'r') (k,v) = ('','') is_multi_line = False for line in fp.readlines(): line = line.strip() #space line or commentted line will be ignored if len(line) == 0 or line.startswith('#'): continue #end with character(\), multi-line start line if not is_multi_line and line.endswith('\\'): is_multi_line = True #remove the end character(\) and split with character(=) (k,v) = line.replace('\\','').split('=', 1) continue if is_multi_line: #not end with character(\), multi-line end line if not line.endswith('\\'): v = v + ' ' + line props[k.strip()] = v.strip() k = v = '' is_multi_line = False #multi-line else: v = v + ' ' + line.replace('\\','') continue #normail line(key=value) (k,v) = line.replace('\\','').split('=', 1) if len(k.strip()) == 0: continue props[k.strip()] = v.strip() (k,v) = ('','') return props def _unescape_property(self, value): #white space if len(value.strip()) == 0: return #match ${ncs.log.dir} extract_vars = lambda s: [v[1] for v in re.findall(r'^(.*)\${([^}]+)}(.*)$', s)] while extract_vars(value): for var in extract_vars(value): if self.isdebugon(): print("matched key: {0}".format(var)) if not self.properties.has_key(var): print("[warn] matched key not exists: {0}".format(var)) break #matched key exits val = self.properties.get(var) if self.isdebugon(): print("{0} = {1}".format(var, val)) value = value.replace('${'+var+'}', val) #match $ENV{HOME} extract_envs = lambda s: [e[1] for e in re.findall(r'^(.*)\$ENV{([^}]+)}(.*)$', s)] while extract_envs(value): for env in extract_envs(value): if self.isdebugon(): print("matched environ: {0} = {1}".format(env, os.getenv(env,''))) value = value.replace('$ENV{'+env+'}', os.getenv(env,'')) return value def _unescape_properties(self): for (key,value) in self.properties.items(): self.properties[key] = self._unescape_property(value) def get(self, key, default=None): return self.properties.get(key, default) def getint(self, key, default=0): int(self.get(key,default)) def getlong(self, key, default=0): long(self.get(key,default)) def getfloat(self, key, default=0.0): float(self.get(key,default)) def getboolean(self, key, default=False): value = self.get(key) if value: return True return default or False def getrange(self, key): result = [] value = self.get(key) if value: for val in value.split(','): #val as range if '-' in val: (start,end) = val.split('-', 1) result.extend(range(int(start),int(end)+1)) else: result.append(int(val)) return result def set(self, key, value=None): self.properties[key] = value def search(self, keywords): props = {} for (key,value) in self.properties.items(): if keywords in key: props[key] = value return props def size(self): return len(self.properties.items()) def dump(self): for key in sorted(self.properties.keys()): print("{0} = {1}".format(key,self.properties.get(key))) def import_properties(self, properties, override=False): for (key,value) in properties.items(): if self.properties.has_key(key) and not override: continue self.properties[key] = value def import_from_file(self, resource, override=False): properties = self._parse(resource) self.import_properties(properties, override)
发表评论
-
Perl常用函数集
2012-04-26 10:05 818#!/usr/bin/perl -w package C ... -
用Perl发送邮件
2012-04-26 10:02 1047#!/usr/bin/perl -w package M ... -
Ruby版网路爬虫
2011-06-17 13:54 1460很早之前写的一个爬虫,抓取数据并存放mysql数据库,支持多线 ... -
Ruby版给图片加水印
2011-06-17 13:45 990ImageUtils.rb #!/usr/local/bi ... -
NCS(Nightly CoSIM Script)
2011-06-14 15:45 858NCS(Nightly CoSIM Script)包括Perl ...
相关推荐
在这个场景中,我们关注的是如何使用Perl来解析Excel文件。Excel文件通常包含表格数据,这对于数据分析、报告生成或自动化工作流程非常有用。Perl提供了多种库来处理这种任务,其中最常用的是Spreadsheet::ParseXLSX...
标题和描述概述的知识点主要集中在Perl与Python的对比分析,涉及两者的起源、特性、哲学理念,以及在基本数据类型上的差异。以下是对这些知识点的深入解析: ### Perl与Python的起源和特点 #### Perl - **起源**...
Pod是Perl的内置文档格式,与Makefile解析无关,但它是Perl社区常用的文档编写方式。这个模块可能提供了一种解析Pod文档到其他格式(如HTML、man页等)的工具。 总的来说,Perl编写的Makefile解析器对于理解和优化...
在这个案例中,Perl程序可能封装了读取和查询QQWry数据库的过程,这可能涉及到了文件I/O和字符串解析技巧。 在安装和使用这个Perl包时,可能会有一些依赖条件需要满足。常见的Perl依赖包括CPAN(Comprehensive Perl...
### Perl之读取文本文件知识点解析 #### 一、Perl简介 Perl是一种广泛使用的脚本语言,特别适合于文本处理和快速原型开发。它具备强大的正则表达式支持能力,可以方便地处理字符串数据。 #### 二、读取文本文件的...
Perl中的XML::Simple模块是Perl社区广泛使用的XML解析器,尤其适合处理小型或结构简单的XML文档。这个模块的名称虽然包含“Simple”,但它实际上提供了一种简洁的接口,用于将XML数据转换为Perl数据结构,反之亦然。...
该脚本用于解析asc文件并筛选指定can信号,输出到csv文件中。 1、该版本已部分优化,使用m语言以及perl语言编程,大幅提高效率; 2、资源为源码,附有部分注释; 3、脚本可以同时解析多个asc文件,命名方式为0.asc、...
标题提到的“最好用的Lua,Python,Perl,Ruby,NSIS开发编辑器”显然是一款集成了多种编程语言支持的高效工具,它旨在为使用这些语言的开发者提供便利。这款编辑器可能包含了丰富的特性,如语法高亮、代码提示、调试...
perl5.10.1安装文件perl5.10.1安装文件perl5.10.1安装文件perl5.10.1安装文件perl5.10.1安装文件perl5.10.1安装文件perl5.10.1安装文件
这篇博客文章“perl读写xml文件”很可能是关于如何在Perl中操作XML文件,包括解析XML内容、提取数据、修改数据以及生成新的XML文件。 Perl提供了多个模块来处理XML,最常用的是XML::Simple和XML::LibXML。XML::...
然后,下载与Perl版本兼容的`dmake`源码或者预编译的二进制包。由于这里提供的压缩包名为`site`,我们可以推测其中可能包含了已经编译好的`dmake`二进制文件和其他必要的支持文件。解压缩后,将整个`site`目录覆盖到...
在IT领域,特别是Web开发中,文件上传是一个常见的需求,涉及到客户端与服务器之间的数据交互。在给定的文件信息中,我们看到了一个基于Perl语言实现的文件上传解决方案,包括前端HTML表单设计和后端Perl脚本处理。...
标题“Perl实现文件及数据库访问”揭示了这个主题主要关注如何使用Perl编程语言来操作文件以及与数据库进行交互。Perl是一种强大的脚本语言,尤其在处理文本和系统管理任务方面非常出色。在这个主题中,我们将深入...
3. **跨平台兼容性**:虽然Perl具有良好的跨平台特性,但在不同操作系统中,文件的时间戳可能有所不同(如Windows与Unix/Linux之间)。在编写涉及文件时间戳的脚本时,确保其在目标平台上正确运行是非常重要的。 ...
Ruby的语法设计深受Perl和Smalltalk的影响,具有以下特点: 1. **动态类型**:Ruby是动态类型的,这意味着变量的数据类型是在运行时确定的,无需提前声明。这使得编程更为灵活,但也可能导致一些运行时错误。 2. *...
在这个场景中,我们有一个Perl替换脚本,它被设计用来方便地在文本文件中批量替换特定的单词。下面将详细介绍这个脚本的工作原理和使用方法。 首先,我们需要理解Perl脚本的基本结构。Perl脚本通常包含变量定义、...
可能太乱了,但是至少可以提供给大家一个范例,使用perl创建xlsx(2007)、读文本文件然后抓取数据生成xlsx文件(具体内容是ezplan提取的drill信息的文本,然后排序 由小到大,第一行指定0.125,第二行0.4,pre放在...
/usr/bin/perl`或类似路径开头,这是Shebang行,告诉系统使用哪个解释器来执行文件。 - 接下来,可以使用`use strict;`和`use warnings;`来开启严格的语法检查和警告,有助于编写更健壮的代码。 - 之后,可以定义...
使用方法简单,在当前目录下,使用perl make_f.pl xx,xx为例化的filelist文件名,按下回车将会生成.f文件,里面列出了当前目录下所有.v文件的绝对路径,将脚本中.v替换成.c也可以检索当前目录下的所有.c文件,...
"Config-Perl"是一个Perl模块,专门设计用来解析那些用Perl语法编写而非传统ASCII格式(如INI或XML)的配置文件。这个模块允许开发者使用Perl的全部语法灵活性来定义配置结构,而不仅仅是简单的键值对。 Config-...