简体   繁体   English

Converter Perl脚本修复

[英]Converter Perl script fix

I am trying to use a small Perl script in order to convert SQL INSERT statements from MySQL syntax into SQLite syntax. 我试图使用一个小的Perl脚本,以便将SQL INSERT语句从MySQL语法转换为SQLite语法。 But the script has a bug and can't convert the string constants properly in some corner cases. 但是该脚本有一个错误,在某些特殊情况下无法正确转换字符串常量。

Here is the script: 这是脚本:

#!/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;
}

The problem is that in the case of the following MySQL string: 问题是在以下MySQL字符串的情况下:

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

It generates wrong SQLite string: 它生成错误的SQLite字符串:

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

instead of the proper: 而不是适当的:

'It doesn''t work :-\'

What is wrong in the script? 脚本有什么问题?

EDIT: 编辑:

And how to fix it? 以及如何解决?

It's because you're processing \\' before \\\\ . 这是因为您要在\\\\之前处理\\' You need to handle backslashes in the order they are encountered, so you need to do everything in one pass. 您需要按遇到的顺序处理反斜杠,因此您需要一次性完成所有操作。

#!/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;
}

Note the proper way of optionally matching UN . 请注意可选地匹配UN的正确方法。

The first substitution s/\\\\'/''/g; 第一个替换s/\\\\'/''/g; replace the last \\' by '' , so ''替换最后一个\\' '' ,所以

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

becomes 变成

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

I guess you want to replace \\' only when it is not followed by a non-word character \\W . 我猜您只想在不带非单词字符\\W后才替换\\'

I'm using here only the 2 relevant substitutions for this case 我在这里只使用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;

Output: 输出:

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM