我正在尝试使用一个小的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 :-\'
脚本有什么问题?
编辑:
以及如何解决?
答案 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);