用于替换数据库插入语句中的引号的正则表达式

时间:2009-08-21 19:08:17

标签: regex sqlite sed dump

我正在将sqlite3数据库转换为mysql。

我有一个很好的sed命令文件,可以更改AUTOINCREMEMT以及其他需要的东西,但是我被困在最后一个:双引号。

sqlite3转储格式:

CREATE TABLE "products" (
  "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 
  "name" varchar(255), 
  "desc" varchar(255) );

INSERT INTO "products" VALUES(1,'Flux Capacitor',
  'This is the "real" thing.\nPromise!')

对于第一个语句,我可以用反引号替换所有双引号,mysql会很高兴。

但是,我的产品信息在数据中有双引号。如何排除这些被替换?我试图用占位符替换那些双引号,然后我可以替换所有其他双引号,然后我可以更改占位符,但我的正则表达式不符合标准。

这是我得到的:

/"[^"]*"/s

...匹配双引号文本,但我无法弄清楚如何限定单引号内的双引号应匹配。

3 个答案:

答案 0 :(得分:3)

我会更改MySQL以接受双引号作为标识符分隔符。这是标准的SQL行为,您可以使MySQL以这种方式使用SQL模式:

mysql> SET SQL_MODE = ANSI;

或更具体地说:

mysql> SET SQL_MODE = ANSI_QUOTES;

然后MySQL应该了解你的数据转储。

有关详细信息,请参阅“Server SQL Modes”。

答案 1 :(得分:0)

我知道如何使用preg_replace_callback()在PHP中轻松解决它:


<?php

    $sql = file_get_contents('sqlite3 dump.txt');
    function callback($match) { return str_replace('"', '`', $match[0]); }
    $sql = preg_replace_callback('/CREATE TABLE .*?;/s', callback, $sql);
    echo preg_replace_callback('/INSERT INTO .*? VALUES/s', callback, $sql);

?>

除非你能像Bill Karwin所说的那样“设置SQL_MODE = ANSI_QUOTES”。

答案 2 :(得分:0)

  

我可以用反引号替换所有双引号,mysql会很高兴。

现在开心,但它不会解决整个问题,所以很容易在将来垮掉。撇号和反斜杠在MySQL中也有不同的作用。

  

我的商品信息在数据中有双引号。如何排除这些被替换?

你不能可靠。 SQL语法实际上非常复杂,在一般情况下不能通过正则表达式黑客进行解析。

Bill建议改变SQL_MODE以适应现有语法是一种更好的方法。我一直在ANSI模式下运行MySQL,因为我不喜欢将我的应用程序定制到一个特定数据库的弱点。