2

我是 perl 脚本的新手。我正在编写脚本来读取 excel 文件并以 C 编程语法放入文本文件。

所以我的excel表我有如下字符串:

If ((Myvalue.xyz == 1) Or (Frmae_1.signal_1 == 1)) Then a = 1
else a = 0;

我必须将其转换为:

a = (((Myvalue.xyz == 1) || (Frmae_1.signal_1 == 1))?1:0)

在 perl 中如何处理?

4

3 回答 3

8

我认为在代码字符串中添加正则表达式并不是一个特别好的主意。您输入的语法看起来并不太特别,所以我们可以使用 Marpa 解析它,使用类似的语法

:default    ::= action => [values]
:start      ::= StatementList
:discard    ~   ws

StatementList ::= <Expression>+ separator => <op semicolon> bless => Block

Expression ::=
        ('(') Expression (')')  assoc => group action => ::first
    |   Number                  bless => Number
    ||   Ident                  bless => Var
    ||  Expression  ('==')  Expression  bless => Numeric_eq
    ||  Expression  ('=' )  Expression  bless => Assign
    ||  Expression  ('Or')  Expression  bless => Logical_or
    ||  Conditional

Conditional ::=
        ('If') Expression ('Then') Expression
            bless => Cond
    |   ('If') Expression ('Then') Expression ('Else') Expression
            bless => Cond

Ident   ~ ident
Number  ~ <number int> | <number rat>

word    ~ [\w]+
ident   ~ word | ident '.' word
<number int> ~ [\d]+
<number rat> ~ <number int> '.' <number int>
ws      ~ [\s]+
<op semicolon> ~ ';'

然后:

use Marpa::R2;
my $grammar = Marpa::R2::Scanless::G->new({
    bless_package => 'Ast',
    source => \$the_grammar,
});
my $recce = Marpa::R2::Scanless::R->new({ grammar => $grammar });
$recce->read(\$the_string);
my $val = $recce->value // die "No parse found";
my $ast = $$val;

一旦我们有了 AST,将其编译为类似 C 的表示形式并不太复杂。通过“优化”传递来分解出常见的分配可以通过一些思考来完成。

然而,展示如何做到这一点相当冗长,所以我把所有深入的东西都放在了这篇文中。然后我们可以定义一个通过树递归并发出类 C 代码的方法,例如

package Ast::Var;
...;
sub compile { my $self = shift; $self->name } # no modification needed

package Ast::Logical_Or;
...;
sub compile {
  my $self = shift;
  # C's "||" operator, plus parens to specify precedence
  "(" . $self->l->compile . "||" . $self->r->compile . ")";
}

package Ast::Cond;
...;
sub compile {
  my $self = shift;
  return sprintf '(%s ? %s : %s)',
      $self->cond->compile,
      $self->then->compile,
      $self->else->compile;
}

等所有其他 AST 节点类型。

于 2013-06-26T13:23:23.537 回答
0

相同的表达式在 Perl 中有效(取模访问运算符,->在 perl 中而不是点。你也可以这样做

a = $my_value->xyz == 1 || $frmae_1->signal_1 == 1 ? 1 : 0;

? 1 : 0部分甚至不是必需$my_value->xyz == 1 || $frmae_1->signal_1 == 1的,因为它将返回 Perl 真或假值(数字10,字符串'1''')......

于 2013-06-24T13:11:21.707 回答
0

说,您的字符串存储在$str. 您可以执行以下操作以从中提取内容:

my ($cond, $set, $then, $else) = ($str =~ /^If (.*) Then (.*?=\s+)(.*) else \2(.*);$/);

现在你在 , in 中有了你的条件$conda =在and$set中的那个变量应该是什么。$then$else

在您的情况下替换“或”和“和”

$cond =~ s/\sOr\s/ || /g;
$cond =~ s/\sAnd\s/ && /g;

并打印您想要的输出

print "$set($cond ? $then : $else);

这些正则表达式适用于您的字符串:我得到了

a = (((Myvalue.xyz == 1) || (Frmae_1.signal_1 == 1)) ? 1 : 0)

但是如果您的实际字符串将“Then”写为“then”,则可能会失败,如果某些字符串中的“Myvalue.xyz”是“Myvalue.And”或类似的东西,则会爆炸。如果周围没有空格=Or. 但是可以轻松修改代码以使用所有这些输入。小心正则表达式,它们很强大。

于 2013-06-24T13:22:56.440 回答