正则表达式 perl
字符串操作符
.?用于連接字符串
use warning 開啟per內置的警告信息,或者用-w參數
use diagnostics 查看更多編譯信息或者用-Mdiagnostics參數
讀到文件結尾end-of-line時,返回undef標志,用defined函數是否是undef狀態。
標量都是單數(singular),列表與數組代表復數(plural)
列表(list)指的是標量的有序集合,而數組(array)則是存儲列表的變量
或者說列表指的是數據,而數組指的是變量
$rocks[$#rocks]? $rocks[-1]等效 都指最后一個
("aaa","bbb","ccc","ddd")
qw(aaa,bbb,ccc,ddd)兩等效
Perl允許使用任何標點符號作為定界符,常用的有:
qw! aaa bbb ccc ddd !
qw/ aaa bbb ccc ddd /
qw# aaa bbb ccc ddd #
@arrayname 引用整個數組
push-pop操作數組尾和shift-unshift操作數組首
splice
@array = qw(aaa,bbb,ccc,ddd,eee);
@removed = splice @array,2;
#?@removed變成qw(ccc,ddd)
#?@array變成qw(aaa,bbb)
foreach(1..10){
?print "this num is $_!\n"???#??? $_ 默認變量
}
state來聲明為當前子程序的持有性私有變量,并且多次調用這個子程序期間保留該變量的值。
chomp;??#不加參數,默認用默認參數$_
@ARGV #命令行默認參數
6個特殊文件句柄是Perl保留的,STDIN,STDOUT,STDERR,DATA,ARGV,ARGVOUT
數組用方括號,哈希用花括號
$hash{ 'index1' } = 'index1value';
哈希函數
$reverhash = revers %hash
my @k = keys %hash;
my @v = values %hash;
while(($key,$value) = each %hash)
{}
exists/delete
%ENV
print "PATH is $ENV{PATH}\n"
正則表達式
$_ = "yabba dabba doo";
if( /abba/ )
{..}
Unicode屬性,Unicode字符能夠理解自身含義,它們包含字節組合之外,還附帶著屬性信息。
if(/\q{Space}/){}
if(/\q{Digit}/){}
元字符
點號(.)是能匹配任意一個字符的通配符,換行符除外。
/3\.14159/這個模式中點號就不是表示通配的元字符
星號(*)正是用來匹配前面的條目零次或任意多次的
/abb\t*bbb/?匹配abb\tbbb? abb\t\tbbb
/aaa.*bbb??因此會匹配任意字符零次到無限多次
加號(+)也是量詞,會匹配前一個條目一次以上
問號(?),前面條目可出現一次或不出現
模式分組
/fred*/?匹配freddddd
/(fred)*/ 匹配fredfred
反向引用來引用圓括號中的模式所柳丁的文字,這個行為我們稱為捕獲組,
比如\1?\2表示相應順序的捕獲組
$_ = "abb";
if(/(.)\1/){}?#匹配 ‘bb'
/y(.)(.)\2\1/ #匹配?’abba'
“aa11bb"
\111??是指\111,而不是\1或\11, Perl盡可能往多的原則靠
if(/(.)\g{1}11/)?指\1??解決反引用與直接量部分的二義性
if(/(.)\111/)???指\111
if(/(.)(.)\g{-1}11/?相對自己的位置來找編號
擇一匹配
/fred(|\t)+barney/
字符集,指的是一組可能出現的字符,通過寫在方括號([])內表示。
[abcwxyx]?匹配7個字符內任意一個
[\000-\177] 將匹配任意一個7位的ASCII字符
[^def]會匹配這三個字符以外的任何字符???^ 脫字符
字符集的簡寫
比如表示任意一個數字的字符集的簡寫是\d
\s簡寫能匹配任意空白符,所以效果上大抵等同于Unicode屬性\p{Space}
Perl5.6之前,\s僅能匹配5個 換頁符,水平制表符,換行符,回車符,空格
\h?只匹配水平空白符
\v?只匹配垂直空白符
\R簡寫能匹配任意一種斷行符
\w能匹配的字符并不是嚴格意義上的單詞字符
[^\d],[^\w],[^\s] 非數字,非單詞或者非空白符
[\D],[\W],[\S] 大寫版本表示否定意義
[\d\D],表示任何數字或非數字,也就是匹配任意字符(包含換行符),而點號不匹配換行符
正則表達式進行匹配
用m//進行匹配
/i進行大小寫無關的匹配
/s匹配任意字符?? 點號無法匹配換行符,對單行點號就適用了
?$_ = "I saw Barney\ndown at the bowling alley\nwith fred\nlast night.\n"
?if(/Barney.*Fred/s){}?沒有/s修飾符,匹配會失敗。
/x加入空白符
?/-?[0-9]+\.?[0-9]*/
?/ -? [0-9]+ \.? [0-9]* /x??#這樣便于閱讀,理解,但原來的空白和制表本身需要用\空格和\t
組合選項修飾符
?if(/barney.*fred/is){}
三種字符解釋方式:ASCII(/a),Unicode(/u)和locale(l),locale經常會引發問題。
錨位,可以讓模式僅在字符串指定位置匹配。
\A錨位匹配字符串的絕對開頭,如果開頭位置不匹配,是不會順移到下一個位置繼續嘗試的。
m{\Ahttps?://}i??#判斷字符串是否以https開頭
m{\.png\z}i????#匹配以.png結尾的
字符串的絕對末尾,強調后面再無任何其他東西。 \Z允許后面出現換行符
while(<STDIN>){
?print if /\.png\Z/;
}
while(<STDIN>){
?chomp;
?print "$_\n" if /\.png\z/;
}
可以用$錨位和/m修飾符表示對多行內容進行匹配。
/fred$/m
單詞錨位
/\bfred\b/可匹配fred,但無法匹配frederick,alfred,manfredss。\b是單詞邊界錨位,也稱為”整詞匹配“
綁定操作符=~
默認情況下模式匹配的操作對象是$_,綁定操作符(=~) 告訴perl用右邊的模式來匹配左邊的字符串。
模式中的內插
my $what = "larry";
while(<>){???#每次讀一行輸入
?if(/\A($what)/){?#模式的錨位被定在字符串的開頭
??print "We saw $what in beginning of $_";
?}
}
除非while循環的條件表達式中只有整行輸入操作符(<STDIN>) ,否則輸入行不會被 PERL自動存入$_.
捕獲變量
捕獲組會把匹配圓括號中模式的字符串保存到相應的地方$1,$2,$3
$_ = "Hello there, neighbor";
if(/(\S+) (\S+),(\S+)/){
?print "word were $1 $2 $3\n";
}
運行結果是:words were Hello there neighbor.
捕獲變量的存續期, 它們能戚到下次成功匹配為止。失敗的匹配不會改動上次成功匹配時捕獲的內容。
不捕獲模式:用?:修飾的圓括號不會將捕獲部分的匹配字符串放到捕獲變量中
if(/(?:bronto)?saurs (steak|burger){
?print "Fred wants a $1\n";
}
命名捕獲
my $names = 'Fred or Barney';
if( $names =~ m/(?<name1>\w+) (?:and|or) (?<name2>\w+/){
?say "i saw $+{name1} and $+{name2}";
}
自動捕獲變量:$&,$`,$'免費但影響運行速度
字符串里實際匹配模式的部分會被自動在存進$&里
if( "Hello there, neighbor" =~ /\s(\w+),/){
?print "That actually matched '$&'.\n";
}
$1保存there
$&保存there,
匹配區段之前的內容會存到$`里,匹配區段之后的內容則會存到$'里
用/p修飾符則可用${^PREMATCH},${^MATCH}和${^POSTMATCH}表示。
用正則表達式處理文本
用s///進行替換
$_ = "He's out bowling with Barney tonight.";
s/Barney/Fred/;?#把Barney替換為Fred
print "$_\n";
s/Barney/Fred/g;?#/g 全局替換
my @filelds = split /separator/, $string;
my @fields = split /:/, "abc:def:g:h";?#得到("abc","def","g","h")
join函數功能與split相反
my $result = join $glue, @pieces;
my $x = join ":", 4,6,8,10,12;?# $x為"4:6:8:10:12"
$_ = "Hello there, neighbor";
my($first,$second,$third) = /(\S+) (\S+), (\S+)/;
print "$second is my $third\n";
貪婪量詞
/fred.+barney/??#要求能匹配的字符串越長越好
非貪婪量詞
/fred.+?barney/??#要求能匹配的字符串越短越好
if(flag){...}???#flag為真時才執行
unless(flag){...}?#flag為假時才執行
while(flag){...}?#flag為真時才執行
until(flag){...}?#flag為假時才執行
last操作符能立即中止循環的執行,相當C語言中的"break"
next相當continue
redo操作符返回到當前循環塊的頂端,而不經過任何條件測試,也不會進入下一次循環迭代。
LINE:while(<>){
?foreach(split){
??last LINE if /__END__/;
??...
?}
}
die "Oops! A file called '$filename' already exist.\n"
?if -e $filename;
PERL 模塊
perldoc CGI 打開模塊文檔
perl自帶cpan命令查看所有模塊: $cpan -a
模塊使用MakeMaker
$perl Makefile.PL
$make install
使用Module::Build
$perl Build.PL
$./Build install
perl自帶的path::class模塊則提供了更友好的操作界面:
my $dir??=?dir( qw(Users fred lib) );
my $subdir= $dir ->subdir( 'perl5' );?# Users/fred/lib/perl5
DateTime處理日期和時間的模塊
chdir操作符來改變當前的工作目錄
my @all_files = <*>;
my @all_files = glob "*";
Perl里面,可以使用unlink操作符,并指定要刪除的文件列表。
rename函數
chmod函數類似unix的chmod命令
chmod 0755, 'fred', 'barney';
字符串與排序
$where = index($big, $small);
?$big = "Howdy world!";
?$where = index($big, "wor");??# $where is 6?
my $part = substr($string, $initial_position, $length);
省略第三參數將取到字符串結尾
$initial_position? 負數表示從后數起
substr($string, -20) =~ s/fred/barney/g;?#? 將后面20字符所有fred換成barney
sprintf函數與printf有相同的參數
my $date_tag = sprintf "%4d/%02d",$yr,$mo;
hex('DEA')
oct('0377')
智能匹配
use 5.010001
say "I found Fred in the name!" if $name ~~ /Fred/;
等價以下:
my $flag = 0;
foreach my $key (keys %names ){
?next unless $key =~ /Fred/;
?$flag = $key;
?last;
}
print "I found Fred in the name!" if $flag;
given-when類似switch
given ( $ARGV[0] ){
?when ( 'Fred' ){say 'Name is Fred' }
?when ( /fred/i ){say 'Name has fred in it' }
?defalut{say 'ss'}
}
進程管理
system 'date'; ?# perl調用unix的date命令。
exec
捕獲錯誤
eval { $barney = $fred / $dino };
eval只是一個表達式,末尾加”;"
捕獲到錯誤eval將返回undef,如果沒有錯誤發生,$@就是空的
exit操作符會立即終止程度運行。
異常機制
die拋出異常
eval {
?...;
?die "An unexpected exception message" if $unexpected;
?die "Bad denominator" if $dino == 0;
?$barney = $fred / $dino;
}
if( $@ =~ /unexpected/ ){
?...;
}
elsif( $@ =~ /denominator/ ){
?...;
}
{
local $@;?#不干擾高層錯誤
...
}
foreach( 1..1000){
?push @odd_numbers, $_ if $_ % 2;
}
等價
my @odd_numbers = grep { $_ % 2 } 1..1000;
my @matching_lines = grep /\bfred\b/i, <$fh>;
my $line_count = @matching_lines;
my $line_count = grep /\bfred\b/i, <$fh>;
?
?
<!ELEMENT NXRMClientConfiguration (LocationArray,Log)>
<!ATTLIST NXRMClientConfiguration SchemaVersion CDATA #REQUIRED>
<!ATTLIST NXRMClientConfiguration SN CDATA #REQUIRED>
<!ATTLIST NXRMClientConfiguration Name CDATA #REQUIRED>
<!ATTLIST NXRMClientConfiguration UpdateDate CDATA #REQUIRED>
<!ELEMENT LocationArray (Location+)>
<!ELEMENT Location (#PCDATA)>
<!ATTLIST Location Name CDATA #Default>
<!ATTLIST Location Desc CDATA #REQUIRED>
<!ELEMENT Log (#PCDATA)>
<!ATTLIST Log MaxLogSize CDATA #REQUIRED>
?
#!/usr/bin/perl -w
#this sub function parser sub elment
#usage:
#$result = [];?$subelement = "(A | (B, (C | (D, E))) | F)";
#Subelementparser($result,$subelement);
#return $result = A???B,C???B,D,E????F
sub Subelementparser{
?my($res,$temp)=@_;
?my($prematch,$match,$postmatch);
?my(@items);
?
?$temp =~ s/\s*//g;??# delete space
?$temp =~ s/^\((.*)\)$/$1/e;?#delete outside bracket
?unless($temp =~ /\(/){??#case inside bracket
??if($temp =~ /\|/){
???@items = split(/\|/,$temp);
???foreach (@items){
????push @$res, $_;
???}
??}
??else{
???push @$res,$temp;
??}
?}
?else{???#case:?there exist is one or more bracket
??$temp =~ m/\((.*)\)/;
??$prematch = ${^PREMATCH};
??$match = ${^MATCH};
??$postmatch = ${^POSTMATCH};
??
??$flag = "false";
??if($prematch =~ /,/){
???$flag = "true";
??}
??
??if($flag =~ /true/){??#case: B,(D|E)
???my($tempres) = [];
???Subelementparser($tempres,$match);
???foreach (@$tempres){
????push @$res, "${prematch}$_";?# $prematch = "B,"
???}
??}
??else{
???@items = split(/\|/,$prematch);
???foreach (@items){
????push @$res, "$_";
???}
???if($match =~ /./){
????Subelementparser($res,$match);
???}
??}
?
??@items = split(/\|/,$postmatch);
??foreach (@items){
???if(/./){
????push @$res, $_;
???}
??}
?}
}
sub ProcElement {
?my($cname, $expan)=@_;
?my($cinterdef,$cimpheader,$cimpcpp);
?my($construc, $parser);
?my($mem);
?my($headerfile,$class_name);
?my($subelements) = [];
?Subelementparser($subelements,$expan);
# here start generate .h file without attribute part and } end part
?$cinterdef = "// <!ELEMENT ${cname} ${expan}>\n";
?$cinterdef .= "class I$cname\n{\npublic:\n";
?$cinterdef .= "\tvirtual bool WriteToXML(const std::string& XMLPath) = 0;\n";
?$cinterdef .= "\tvirtual bool ReadFromXML(const std::string& XMLPath) = 0;\n";
?$cinterdef .= "\tvirtual void Reset(void) = 0;\n";
?$cinterdef .= "\tvirtual void Release(void) = 0;\n\n";
?
?$construc = "";
??
?$cimpheader = "class $cname : public I$cname\n{\npublic:\n";
?$cimpheader .= "\t$cname(void);\n";
?$cimpheader .= "\t$cname(const Node& node);\n";
?$cimpheader .= "\t~$cname(void);\n";
?$cimpheader .= "\tbool WriteToXML(const std::string& XMLPath);\n";
?$cimpheader .= "\tbool ReadFromXML(const std::string& XMLPath);\n";
?$cimpheader .= "\tvoid Reset(void);\n";
?$cimpheader .= "\tvoid Release(void);\n\n";
?$cimpcpp = "${cname}::${cname}() : m_node(Node())\n{\n\tm_node.SetNodeName(\"${cname}\");\n}\n\n";
?$cimpcpp .= "${cname}::${cname}(const Node& node) : m_node(node)\n{\n\tm_node.SetNodeName(\"${cname}\");\n}\n\n";
?$cimpcpp .= "${cname}::~${cname}(void)\n{\n}\n\n";
?$cimpcpp .= "bool ${cname}::WriteToXML(const std::string& XMLPath)\n{\n\treturn m_node.Print(XMLPath);\n}\n\n";
?$cimpcpp .= "bool ${cname}::ReadFromXML(const std::string& XMLPath)\n{\n\tm_node = Node(XMLPath);\n\treturn true;\n}\n\n";
?$cimpcpp .= "void ${cname}::Reset(void)\n{\n\tm_node = Node();\n\tm_node.SetNodeName(\"${cname}\");\n}\n\n";
?$cimpcpp .= "void ${cname}::Release(void)\n{\n\tdelete this;\n}\n\n";
?
?foreach (@$subelements){
??@subclass = split(/,/, $_);
#??$cdef .= "\t$cname(";
#??$flag = "false";
??foreach $mem (@subclass){
???if($mem =~ /[?*+]/){
????$mem =~ s/[*+?]//g;
????$cinterdef .= "\t//Element $mem\n";
????$cinterdef .= "\tvirtual unsigned int GetElem${mem}(void) = 0;\n";
??? ??$cinterdef .= "\tvirtual I${mem}* GetElem${mem}At(unsigned int index) = 0;\n";
??? ??$cinterdef .= "\tvirtual void AddElem${mem}(I${mem}* NewElem) = 0;\n";
??? ??$cinterdef .= "\tvirtual void AddElem${mem}At(unsigned int index, I${mem}* NewElem) = 0;\n";
??? ??$cinterdef .= "\tvirtual void RemoveElem${mem}At(unsigned int index) = 0;\n";
??? ??$cinterdef .= "\tvirtual void RemoveAllElem${mem}(void) = 0;\n\n";
??? ??
??? ??$cimpheader .= "\t//Element $mem\n";
????$cimpheader .= "\tunsigned int GetElem${mem}(void);\n";
??? ??$cimpheader .= "\tI${mem}* GetElem${mem}At(unsigned int index);\n";
??? ??$cimpheader .= "\tvoid AddElem${mem}(I${mem}* NewElem);\n";
??? ??$cimpheader .= "\tvoid AddElem${mem}At(unsigned int index, I${mem}* NewElem);\n";
??? ??$cimpheader .= "\tvoid RemoveElem${mem}At(unsigned int index);\n";
??? ??$cimpheader .= "\tvoid RemoveAllElem${mem}(void);\n\n";
??? ??
??? ??$cimpcpp .= "//Element $mem\n";
????$cimpcpp .= "unsigned int ${cname}::GetElem${mem}(void)\n{\n\treturn m_node.NumChilds();\n}\n\n";
??? ??$cimpcpp .= "I${mem}* ${cname}::GetElem${mem}At(unsigned int index)\n{\n";
??? ??$cimpcpp .= "\t${mem} *temp = NULL;\n\tunsigned int total = m_node.NumChilds();\n\tif(index < total)\n\t{\n";
??? ??$cimpcpp .= "\t\ttemp = new ${mem}(m_node.GetChildAt(index));\n\t}\n\treturn temp;\n}\n\n";
??? ??$cimpcpp .= "void ${cname}::AddElem${mem}(I${mem}* NewElem)\n{\n\tm_node.AppendChild(static_cast<${mem}*>(NewElem)->m_node);\n}\n\n";
??? ??$cimpcpp .= "void ${cname}::AddElem${mem}At(unsigned int index, I${mem}* NewElem)\n{\n\tm_node.AppendChildAt(index,static_cast<${mem}*>(NewElem)->m_node);\n}\n\n";
??? ??$cimpcpp .= "void ${cname}::RemoveElem${mem}At(unsigned int index)\n{\n\tm_node.RemoveChildAt(index);\n}\n\n";
??? ??$cimpcpp .= "void ${cname}::RemoveAllElem${mem}(void)\n{\n\tm_node.RemoveChilds();\n}\n\n";?
???}
???elsif($mem =~ /#PCDATA/){
???}
???else{
????$cinterdef .= "\t//Element $mem\n";
????$cinterdef .= "\tvirtual I${mem}* GetElem${mem}(void) = 0;\n";
????$cinterdef .= "\tvirtual void SetElem${mem}(I${mem}* ElemName) = 0;\n\n";
????
????$cimpheader .= "\t//Element $mem\n";
????$cimpheader .= "\tI${mem}* GetElem${mem}(void);\n";
????$cimpheader .= "\tvoid SetElem${mem}(I${mem}* ElemName);\n\n";
????
????$cimpcpp .= "//Element $mem\n";
????$cimpcpp .= "I${mem}* ${cname}::GetElem${mem}(void)\n{\n\treturn new ${mem}(m_node.GetFirstChild());\n}\n\n";
????$cimpcpp .= "void ${cname}::SetElem${mem}(I${mem}* ElemName)\n{\n\tm_node.AppendChild(static_cast<${mem}*>(ElemName)->m_node);\n}\n\n";
???}
??}
?}
?my(%hash) = ();
?undef %hash;
?foreach (@$subelements){
??@subclass = split(/,/, $_);
??foreach $mem (@subclass){
???if(/#PCDATA/){
#????$cdef .= "\tvoid addData( const std::string& data );\n";
???}
???else{
?????unless(exists( $hash{ $mem} ))
?????{
#??????$cdef .= "\tvoid addNode( $mem *the_$mem );\n";
??????
??????$mem =~ s/[*+?]//g;
??????$headerfile .= "#include \"${mem}.h\"\n";
??????$class_name .= "class I${mem};\n";
??????$hash{$mem} = 1;
?????}
???}
??}
?}
?if($rootflag =~ /false/)
?{
??$construc .= "\nconst char* dtdData = \"$tempdtd\";\n\n";
#??$cdef .= "\tbool Validate() const;\n";
#??$cdef .= "\t$cname(const std::string& XMLFile);\n";
?}
#?$cdef .= "};\n\n";??#wait for attribute
?
# here start generate .cpp file
?undef %hash;
?foreach (@$subelements){
??$construc .= "${cname}::${cname}(";
??@subclass = split(/,/, $_);
??$flag = "false";
??foreach $mem (@subclass){
???if( $flag =~ /true/ ){
????$construc .= ",";
???}
???if(/#PCDATA/){
????$construc .= " const std::string& data";
????$parser?.= "void ${cname}::addData(const std::string& data)\n{\n";
????$parser .= "\tSetData(data);\n}\n\n";
???}
???else{
????$construc .= " $mem *the_$mem";
????unless(exists( $hash{ $mem} ))
?????{
?????$parser?.= "void ${cname}::addNode($mem *the_$mem)\n{\n";
?????$parser?.= "\tAppendChild(*the_$mem);\n}\n\n";
?????$hash{$mem} = 1;
????}????
???}
???if( $flag =~ /false/ ){
????$flag = "true";
???}
??}
??
?if($rootflag =~ /false/)
?{
??$parser .= "bool ${cname}::Validate() const\n{\n";
??$parser .= "\treturn ValidateDTD(dtdData);\n";
??$parser .= "}\n\n";
??$parser .= "${cname}::${cname}(const std::string& XMLFile):Node(XMLFile)\n{\n";
??$parser .= "}\n\n";
??$rootflag = "true";
?}
??
??
??$construc .= " ):Node()\n{\n";
??$construc .= "\tSetNodeName(\"${cname}\");\n";
??foreach $mem (@subclass){
???if(/#PCDATA/){
????$construc .= "\taddData(data);\n";
???}
???else{
????$construc .= "\tAppendChild(*the_$mem);\n";
???}
??}
??$construc .= "}\n\n";
?}
?push(@classes, $cname);
?$interfacefile{ $cname } = $cinterdef;
?$implementheaderfile{ $cname } = $cimpheader;
?$implementcppfile { $cname } = $cimpcpp;
?
#?$constructors{ $name } = $construc;
#?$parsersvec{ $name } = $parser;
?$headerlist{ $cname } = $headerfile;
?$classdeflist{ $cname } = $class_name;
}?
sub ProcAttList {
?my($name, $attribs)=@_;
?my($attrib, $atype, $ctype, $condit, $options, $deft);
?my(@options);
?my($builder);
?my($elemtype, $arrlen, $subparse, $req);
?die "ATTLIST $name without ELEMENT\n" if(!defined($interfacefile{ $name }));
?# bin some whitespace
?$attribs =~ s/^\s*//;
?$attribs =~ s/\s*$//;
?while(1){
??if($attribs =~ /^(\w+)\s+(\w+)\s+\#(\w+)\s*(.*)/){??# basic; whatever type
???$attrib=$1;
???$atype=$2;
???$condit=$3;
???$attribs=$4;
???$interfacefile{ $name} .= "\t//Get/Set functions for attribute $attrib\n";
???$interfacefile{ $name} .= "\tvirtual std::string Get$attrib(void) = 0;\n";
???$interfacefile{ $name} .= "\tvirtual void Set$attrib( const std::string& value ) = 0;\n";
???
???$implementheaderfile{ $name} .= "\t//Get/Set functions for attribute $attrib\n";
???$implementheaderfile{ $name} .= "\tstd::string Get$attrib(void);\n";
???$implementheaderfile{ $name} .= "\tvoid Set$attrib( const std::string& value );\n";
???
???$implementcppfile{ $name} .= "//Get/Set functions for attribute $attrib\n";
???$implementcppfile{ $name} .= "std::string ${name}::Get$attrib(void)\n{\n\treturn m_node.GetAttribute(\"$attrib\");\n}\n\n";
???$implementcppfile{ $name} .= "void ${name}::Set$attrib( const std::string& value )\n{\n\tm_node.SetAttribute(\"$attrib\",value);\n}\n\n";
???
???$builder .= "void ${name}::Set$attrib( const std::string& value ){\n\tSetAttribute(\"$attrib\",value);\n}\n\n";
#???$attributparser{ $name } .= $builder;
??}
??else{
???last;
??}
?}
}
# dtd on command line
$flag = "false";
$dtdf = undef();
my($curdir) = `pwd`;
chomp($curdir);
my($outdir) = undef();
my($cppfilename) = "xml_nxl";
$count = @ARGV;
if($count == 1){
?if($ARGV[0] =~ m{\.dtd\z}i){
??$dtdf = $ARGV[0];
?}
?else{
??$flag = "true";
?}
}
elsif($count == 3){
?if($ARGV[0] =~ m{\A-o}i){
??$outdir = $ARGV[1];
??$dtdf = $ARGV[2];
?}
?else{
??$flag = "true";
?}?
}
else{
?$flag = "true";
}
die "Usage: dtd2cpp.pl [switches] <document>
??? -o <directory>???? Outputdir - specify output directory
??? -h???????????????? Help - Show Class Generator usage help\n" if ($flag =~ /true/);
if(defined($outdir)){
?die "the directory ${outdir} don't exist!!!\n" unless(-e ${outdir});
?if($outdir =~ m{\/\z}){
??mkdir "${outdir}/include", 0700;
??mkdir "${outdir}/src", 0700;
?}
?else{
??mkdir "${outdir}/include", 0700;
??mkdir "${outdir}/src", 0700;
?}
}
else{
?if($dtdf =~ /(.*)\/(.*)/){
??$outdir = $1;
??mkdir "${outdir}/include", 0700;
??mkdir "${outdir}/src", 0700;
?}
?else{
??$outdir = $curdir;
??mkdir "${outdir}/include", 0700;
??mkdir "${outdir}/src", 0700;
?}
}
# input filename
open(DTD, $dtdf) || die "can't read $dtdf: $!\n";
$dtd=join('', <DTD>);
close(DTD);
$namespacename = "NxconInterface";
@classes=();
%interfacefile=();
%implementheaderfile=();
%implementcppfile=();
#%constructors=();
#%attributparser=();
#%parsersvec=();
#%headerlist=();
%classdeflist=();
$rootflag = "false";
sub GenerateTargetFile{
?my($oriname)=@_;
?my($intername) = ();
?my($headername) = ();
?my($cppname) = ();
# here generate interface header file
?$intername = "I$oriname";
?open (${intername}, ">${intername}.h") || die "Can't write ${intername}.h: $!\n";
?print ${intername} "// this is generated code, do not edit\n";
?print ${intername} "#pragma once\n\n";
?print ${intername} "#include <string>\n\n";
#?print ${name} "#include \"nxl_xml_node.h\"\n";
?print ${intername} $headerlist{ $oriname } if defined($headerlist{ $oriname });
?print ${intername} "namespace ${namespacename}\n{\n";
#debug output message
print "${intername}\n";
?print ${intername} "$classdeflist{ $oriname }\n" if defined($classdeflist{ $oriname });
?print ${intername} $interfacefile{ $oriname } . "};\n\n";
?print ${intername} "extern \"C\" ${intername}* ${intername}_CreateNewInstance(void);\n\n}\n";
?close(${intername});
?
# here generate implement header file
?$headername = "$oriname";
?open (${headername}, ">${headername}.h") || die "Can't write ${headername}.h: $!\n";
?print ${headername} "// this is generated code, do not edit\n";
?print ${headername} "#pragma once\n\n";
?print ${headername} "#include \"I${headername}.h\"\n";
?print ${headername} "#include \"nxl_xml_node.h\"\n";
?print ${headername} "namespace ${namespacename}\n{\n";
?print ${headername} $implementheaderfile{ $headername };
#?print ${headername} "\nprivate:\n\tNode m_node;\n};\n\n}\n";
print ${headername} "\n\tNode m_node;\n};\n\n}\n";
?close(${headername});
?
?$cppname = $oriname;
# here generate implement cpp file?
?open (${cppname}, ">${cppname}.cpp") || die "Can't write ${cppname}.cpp: $!\n";
?print ${cppname} "// this is generated code, do not edit\n\n\n";
?print ${cppname} "#include \"${cppname}.h\"\n\n";
?print ${cppname} "namespace ${namespacename}\n{\n";
#?print ${name} $constructors{ ${name} } ;
#?print ${name} $parsersvec{ ${name} } ;
#?print ${name} $attributparser{ ${name} } if(defined($attributparser{ ${name} }));
?print ${cppname} $implementcppfile{ ${cppname} };
?print ${cppname} "\nI${cppname}* I${cppname}_CreateNewInstance(void)\n{\n\treturn new ${cppname}();\n}\n";
?print ${cppname} "};\n";
?close(${cppname});
?use File::Copy ;
?use strict ;
?move("${curdir}/${intername}.h","${outdir}/include/${intername}.h")||warn "could not copy files :$!" ;
?move("${curdir}/${headername}.h","${outdir}/include/${headername}.h")||warn "could not copy files :$!" ;
?move("${curdir}/${cppname}.cpp","${outdir}/src/${cppname}.cpp")||warn "could not copy files :$!" ;
}
$tempdtd = $dtd;
$tempdtd =~ s/\r\n//g;
?
$dtd =~ s/\n/''/ge;
# run thru the DTD
while(1){
?$dtd =~ s/^(.*?)</</;
#?$dtd =~ s/[*+?]//g;
?if($dtd =~ /^<(.*?)>(.*)$/){
??$elem=$1;
??$dtd=$2;
??if($elem =~ /^\!ELEMENT\s+(\w+)\s+(.*)/){
???print "==>ELEMENT $1,$2\n";
????? ProcElement($1, $2);
??}
??elsif($elem =~ /^\!ATTLIST\s+(\w+)\s+(.*)/){
??#?print "ATTLIST $1\n";
????? ProcAttList($1, $2);
??}
??elsif($elem =~ /^\!\-\-.*\-\-$/){
??#?print "comment\n";
??}
??else {
???print "1111111111111\n";
???warn "can't understand $elem\n";
??}
?}
?else{
??print "parser over\n" if defined($elem);
??last;
?}
}
# class declarations & code
for(@classes){
?GenerateTargetFile($_);
}
# generate Makefile file
open(MAKEFILE, ">Makefile") || die "Can't write Makefile: $!\n";
print MAKEFILE "#
# ! Don't modify this file
#?? Modify Makefile.inc instead
#
ifeq (\$(NLBUILDROOT),)
? \$(error NLBUILDROOT undefined.)
endif
ifeq (\$(NLEXTERNALDIR),)
? \$(error NLEXTERNALDIR undefined.)
endif
#
#? Following master make file can be included:
#??? - master.cxx.mak
#??? - master.csharp.mak
#??? - master.java.mak
#
\$(info Include master makefile: \$(NLBUILDROOT)/scripts/make/master.cxx.mak)
include \$(NLBUILDROOT)/scripts/make/master.cxx.mak
";
close(MAKEFILE);
move("${curdir}/Makefile","${outdir}/Makefile")||warn "could not copy files :$!" ;
# generate Makefile.inc file
open(MAKEFILEINC, ">Makefile.inc") || die "Can't write Makefile: $!\n";
print MAKEFILEINC
"
##############################################################################
#
#? The Makefile.inc will be used by master Makefile
#? under NLBUILDROOT/scripts/make directory.
#
##############################################################################
#
# The name of the target
#
TARGET_NAME=nxxmlconfig
\$(info Makefile.inc for project \$(TARGET_NAME))
#
#? VERSION
#
VERSION_PRODUCT??= \$(VERSION_PRODUCT_RMP)
VERSION_MAJOR??= \$(VERSION_MAJOR_RMP)
VERSION_MINOR??= \$(VERSION_MINOR_RMP)
VERSION_MAINTENANCE = \$(VERSION_MAINTENANCE_RMP)
VERSION_PATCH??= \$(VERSION_PATCH_RMP)
?
#
# The type of target, could be one of following values:
#?? - exe:? An executable file
#?? - lib:? A static library (user/kernel mode)
#?? - dll:? A dynamic link library (user/kernel mode)
#?? - sys:? A kernel driver
#
TARGET_TYPE=dll
#
#? The run mode of target
#?? - kernel
#?? - user
#
TARGET_MODE=user
#? Make sure the sys target run at kernel mode
ifeq (\$(TARGET_TYPE), sys)
? ifeq (\$(TARGET_MODE), user)
??? \$(error A sys target must run at kernel mode.)
? endif
endif
#
#? Additional settings for EXE
#
ifeq (\$(TARGET_TYPE), exe)
? # Application type: CONSOLE or WIN32
? # console: this is a console application
? # win32:?? this is a win32 application
? EXE_TYPE = console
?
? #
? #? Do we need to elevate privilege?
? #?? - Invoke
? #?? - Administrator
? #
? EXE_PRIVILEGE = Invoke
?
? #
? #? Is this a test app?
? #?? - yes
? #?? - no or empty
? #
? #EXE_TESTAPP = yes
?
endif
#
#? Source file
#
SRC = \\";
foreach (@classes){
?print MAKEFILEINC "
???src/$_.cpp?\\";?
}
print MAKEFILEINC "
????? src/nxl_xml_node.cpp
???
?
#
#? Resource file
#? If this variable is empty, a default rc file will be used automatically
#
RCSRC =
#
#? Additional include directories
#
INCPATH += \\
??? \$(NLEXTERNALDIR)/libxml2-2.7.8.win32/include?\\
??? \$(NLEXTERNALDIR)/libxml2-2.7.8.win32/include/libxml?\\
??? \$(NLEXTERNALDIR)/boost/boost_1_55_0?
#
#? Additional library directories
#
LIBPATH += \\
???? \$(NLEXTERNALDIR)/libxml2-2.7.8.win32/lib?\\
???? \$(NLEXTERNALDIR)/boost/boost_1_55_0/libs/\$(BINDIR)?\\
???? \$(NLBUILDROOT)/bin/\$(BINDIR)
#
#? Additional librarys
#
LIBS +=?\\
??libxml2?
";
close(MAKEFILEINC);
move("${curdir}/Makefile.inc","${outdir}/Makefile.inc")||warn "could not copy files :$!" ;
# generate nxxmlconfig.def file
open(DEFFILE, ">nxxmlconfig.def") || die "Can't write nxxmlconfig.def: $!\n";
print DEFFILE "EXPORTS\n";
foreach $tem(@classes){
? print DEFFILE "\tI${tem}_CreateNewInstance\n";
}
close(DEFFILE);
move("${curdir}/nxxmlconfig.def","${outdir}/src/nxxmlconfig.def")||warn "could not copy files :$!" ;
# generate nxxmlconfig_helper.h file
open(HELPERFILE, ">nxxmlconfig_helper.h") || die "Can't write nxxmlconfig_helper.h: $!\n";
print HELPERFILE "#pragma once\n\n";
foreach (@classes){
?print HELPERFILE "#include \"I$_.h\"\n";
}
close(HELPERFILE);
move("${curdir}/nxxmlconfig_helper.h","${outdir}/include/nxxmlconfig_helper.h")||warn "could not copy files :$!" ;
#testtest only for test need, copy main.cpp nxl_xml_node.cpp nxl_xml_node.h
copy("C:/Snow/Ruby/dev/ruby_starter_140507/common/nxl_xml_node.cpp","${outdir}/src/nxl_xml_node.cpp" ) || warn "could not copy files:$!";
copy("C:/Snow/Ruby/dev/ruby_starter_140507/common/nxl_xml_node.h","${outdir}/include/nxl_xml_node.h" ) || warn "could not copy files:$!";
#testtest copy libxml dlls
unless ( -e "${outdir}/debug_win_x86" ){
?mkdir "${outdir}/debug_win_x86",0700;
}
copy("C:/Snow/Ruby/dev/ruby_starter_140507/common/iconv.dll","${outdir}/debug_win_x86/iconv.dll" ) || warn "could not copy files:$!";
copy("C:/Snow/Ruby/dev/ruby_starter_140507/common/zlib1.dll","${outdir}/debug_win_x86/zlib1.dll" ) || warn "could not copy files:$!";
copy("C:/Snow/Ruby/dev/ruby_starter_140507/common/libxml2.dll","${outdir}/debug_win_x86/libxml2.dll" ) || warn "could not copy files:$!";
?
?
?
總結
以上是生活随笔為你收集整理的正则表达式 perl的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UNIX环境高级编程第二版_扫描 版笔记
- 下一篇: 正则表达式 c++