Converter Perl脚本修复

时间:2018-12-22 11:05:00

标签: mysql regex sqlite perl

我正在尝试使用一个小的Perl脚本,以便将SQL INSERT语句从MySQL语法转换为SQLite语法。但是该脚本有一个错误,在某些特殊情况下无法正确转换字符串常量。

这是脚本:

#!/usr/bin/perl
while (<>){
    s/\\'/''/g;                # Use '' instead of \'
    s/\\"/"/g;                 # Use " instead of \"
    s/\\r\\n/\r\n/g;           # Convert escaped \r\n to literal
    s/\\\\/\\/g;               # Convert escaped \ to literal
    s/ auto_increment//g;      # Remove auto_increment
    s/^[UN]*?LOCK TABLES.*//g; # Remove locking statements
    print;
}

问题在于,对于以下MySQL字符串:

'It doesn\'t work :-\\'

它生成错误的SQLite字符串:

'It doesn''t work :-\''

而不是适当的:

'It doesn''t work :-\'

脚本有什么问题?

编辑:

以及如何解决?

2 个答案:

答案 0 :(得分:2)

这是因为您要在\'之前处理\\。您需要按遇到的顺序处理反斜杠,因此您需要一次性完成所有操作。

#!/usr/bin/perl

my %escapes = (
   n => "\n",
   r => "\r",
);

while (<>) {
    s{\\([\Wrn])}{ $escapes{$1} // ( $1 eq "'" ? "''" : $1 ) }eg;
    s/ auto_increment//g;
    next if /^(?:UN)?LOCK TABLES/;
    print;
}

请注意适当地匹配UN的正确方法。

答案 1 :(得分:0)

第一个替换s/\\'/''/g;\'替换最后一个'',所以

'It doesn\'t work :-\\'
#                    ^^

成为

'It doesn\'t work :-\''

我猜想您只想在不带非单词字符\'的情况下替换\W

在这种情况下,我仅在此使用2种相关的替代方法

my $str = <<'EOD';
insert into tbl values ('it doesn\'t work :-\\', 42, 33, 'and this doesn\'t work as well :-\\', 1024);
EOD
say "before: ",$str;
$str =~ s/\\'(?!\W)/''/g;
$str =~ s/\\\\/\\/g;
say "after: ",$str;

输出:

before: insert into tbl values ('it doesn\'t work :-\\', 42, 33, 'and this doesn\'t work as well :-\\', 1024);

after: insert into tbl values ('it doesn''t work :-\', 42, 33, 'and this doesn''t work as well :-\', 1024);