为什么这种替换也会删除空白字符?

时间:2013-08-07 11:45:30

标签: regex perl

我正在编写一个脚本来从文件中提取和转换SQL语句。我需要将sql unloaded froma gupta sqlbase数据库转换为SQLServer可以理解的sql。

一项任务是使用兼容名称替换不允许作为列名的关键字。

在下面的代码中,$ commands是一个包含sql语句的数组引用。 (这里实际上有更多的代码,但我提取它,因为它在这里不应该相关)

my @KeyWords = ("LEFT", "RIGHT", "PERCENT", "FILE", "PRINT", "CROSS", "PLAN", "TOP", "END", "FILE", "Default", "CHECK", "TEXT");

foreach $cmd (@$commands) {

    foreach my $kw (@KeyWords) {
        $cmd =~ s/\b$kw\b[^(]/_$kw/gi;
    }


    push @$converted, $cmd; 
}

这适用于大多数语句,但在以下命令中"DEFAULT"替换为"_DEFAULT而不是"_DEFAULT"。所以第二个引号就丢失了。

  CREATE TABLE SYSADM.SUBTYPE ( ID_SUBTYPE INTEGER NOT NULL, 
  ID_TYPE INTEGER NOT NULL, 
  TYPE VARCHAR(1), 
  BEZEICH VARCHAR(60), 
  NUM_COLOR INTEGER, 
  NUM_TXTCOLOR INTEGER, 
  "DEFAULT" SMALLINT, 
  GENER_ARBA SMALLINT, 
  PROJEKTPLANUNG SMALLINT)

有没有办法修改正则表达式/ substition,这样就不会删除第二个引号?或者另一种方式?

1 个答案:

答案 0 :(得分:3)

[^(]匹配任何不是左开的paranthesis的单个字符。

您希望使用负零宽度前瞻断言:

s/\b$kw\b(?!\()/_$kw/gi;

(或者:(?![(])

您还可以将替换的字符添加回字符串:

s/\b$kw\b([^(])/_$kw$1/gi;

但请注意,这并不适用于所有情况。特别是如果关键字后面没有任何内容,则此模式将不匹配,而零宽度断言将为。