- 论坛徽章:
- 0
|
回复 9# zhlong8
我的代码如下:
我目前只定义了四个宏规则:
n -> 删除MUSTENTER规则
s\d+e\d+ -> 输出 RANGE start end规则
l{[\d+-\d+]|\d+} -> 输出 LEGAL规则
j -> 输出JUMPS模板
这个脚本的主要作用是在需要大量手工输入简单语法规则检查(epidata)时,通过使用宏替换规则生成一个简单的模板,然后使用一个高效的编辑器完成剩余的工作。
一个简单的验证用模板输入如下:
hello,world,s{1-5|7|9},s{good-bye|hello}:l{0|1|99}
haha,q{1-6}c{1-9|12|17|99}c{1-7}:s1e9,l{0|1}
q{7-9}c{1-9}:s1e8,j
目前简单的替换规则语法简单,工作良好;当输入行数超过1000行时比vi/notepad手工编辑效率高50%以上(脚本完成基本内容的输入,手工调整一下几个跳转规则即可)。
脚本长相相当丑陋,继续求可用的库或成熟工具,最好能够在100行以内可以定义10组以下的宏替换规则,完成基本的宏扩展功能;或者能够在1000行以内,可以定义约30个关键字完成一个小的语法生成工具。- #!/usr/bin/perl
- #
- use strict;
- use warnings;
- if (@ARGV < 2) {
- print "Usage:
- $0 inputfile outputfile
- inputfile: formated template file for qes file
- outputfile: .chk file generated from inputfile\n";
- exit 1;
- }
- my ($inp, $outp) = @ARGV;
- print "input file: $inp, output file: $outp\n";
- open IN, "<$inp" or die "open $inp for read failed: $!\n";
- open OUT, ">$outp" or die "open $outp for write failed: $!\n";
- sub do_second_parse(@)
- {
- my @origs = @_;
- my @keys;
- foreach my $orig (@origs) {
- if ($orig =~ /^([^{]*){([^}]*)}(.*)$/) {
- my ($p, $m, $a) = ($1, $2, $3);
- $a = "" if not defined $a;
- my @sps = split(/\|/, $m);
- foreach my $sp (@sps) {
- my ($start, $end) = split(/-/, $sp);
- if (not defined $end) {
- push @keys, "$p$sp$a";
- }
- else {
- if (int($end) > int($start)) {
- push @keys, map { "$p$_$a" } ($start .. $end);
- }
- else {
- push @keys, "$p$sp$a";
- }
- }
- }
- }
- else {
- push @keys, $orig;
- }
- }
- return @keys;
- }
- sub second_parse($)
- {
- my $fp = shift;
- my @keys;
- push @keys, $fp;
- while ( grep {/{.*}/} @keys ) {
- @keys = do_second_parse(@keys);
- }
- return @keys;
- }
- sub parse_key($)
- {
- my $orig = shift;
- my @first_parse = split(/,/, $orig);
- my @keys = ();
- foreach my $fp (@first_parse) {
- push @keys, second_parse($fp);
- }
- return @keys;
- }
- sub parse_rules ($)
- {
- my $orig_rule = shift;
- my %rules = (
- enter => " MUSTENTER\n",
- range => "",
- legal => "",
- jumps => "",
- );
- my @items = split(/,/, $orig_rule);
- if (grep { /^n$/ } @items) {
- enter => "";
- }
- my @ranges = grep { /^s\d+e\d+$/ } @items;
- if (@ranges) {
- my $range = $ranges[0];
- my ($start, $end) = ($range =~ /^s(\d+)e(\d+)$/);
- $rules{range} = " RANGE $start $end\n";
- }
- my @legals = grep { /^l{.*}$/ } @items;
- if (@legals) {
- my $legal = $legals[0];
- my ($lr) = ($legal =~ /^l{(.*)}$/);
- my @bps = split(/\|/, $lr);
- my @aps;
- foreach my $bp (@bps) {
- my ($start, $end) = split(/-/, $bp);
- if (not defined $end) {
- push @aps, $bp;
- }
- else {
- if (int($end) > int($start)) {
- push @aps, ($start .. $end);
- }
- else {
- push @aps, $bp;
- }
- }
- }
- $rules{legal} = " LEGAL\n";
- foreach my $ap (@aps) {
- $rules{legal} .= " $ap\n";
- }
- $rules{legal} .= " END\n";
- }
- if (grep { /^j$/ } @items) {
- $rules{jumps} .= " JUMPS\n";
- $rules{jumps} .= " ###TODO###\n";
- $rules{jumps} .= " END\n";
- }
- my $res = $rules{enter};
- if ($rules{range}) {
- $res .= $rules{range};
- }
- if ($rules{legal}) {
- $res .= $rules{legal};
- }
- if ($rules{jumps}) {
- $res .= $rules{jumps};
- }
- return $res;
- }
- while (<IN>) {
- chomp;
- s/#.*$//;
- s/\s*//;
- next if /^$/;
- my ($key, $rule) = split(/:/, $_);
- my @keys = parse_key($key);
- #use Data::Dumper;
- #print Dumper(@keys);
- my $fmt = parse_rules($rule);
-
- foreach my $_key (@keys) {
- print OUT "$_key\n${fmt}END\n\n";
- }
- }
复制代码 |
|