使用正则表达式选择性地搜索和替换某些行

时间:2010-05-27 10:54:59

标签: regex sed cygwin grep replace

我有一个包含大量SQL语句的文件,例如:

CREATE TABLE "USER" (
    "ID" INTEGER PRIMARY KEY,
    "NAME" CHARACTER VARYING(50) NOT NULL,
    "AGE" INTEGER NOT NULL
);

COPY "USER" (id, name, age) FROM stdin;
1   Skywalker   19
2   Kenobi      57

我希望COPY语句中的列名称为大写且引用:

COPY "USER" ("ID", "NAME", "AGE") FROM stdin;

使用sed,我找到了以下正则表达式:

sed -r 's/([( ])(\w+)([,)])/\1"\U\2\E"\3/g'

替换列名,但它没有足够的选择性,并替换文件中的其他单词:

~/test]$sed -r 's/([( ])(\w+)([,)])/\1"\U\2\E"\3/g' star_wars_example
CREATE TABLE "USER" (
  "ID" INTEGER PRIMARY "KEY",
  "NAME" CHARACTER VARYING("50")NOT "NULL",
  "AGE" INTEGER NOT NULL
);

COPY "USER" ("ID", "NAME", "AGE") FROM stdin;
1   Skywalker   19
2   Kenobi      57

为避免此问题,我希望 sed 仅将我的正则表达式应用于以COPY开头并以FROM stdin;结尾的行。

我已经研究过lookahead / lookbehind,但它们在sed中不受支持。它们似乎在super-sed中得到支持,但我目前正在使用Cygwin(Windows在这里是强制性的......)并且它似乎在包列表中不可用。

有没有办法强制 sed 只考虑特定的行?

在应用 sed 之前,我已经考虑通过 grep 管道我的文件,但其他行将从输出中消失。

我错过了一些明显的东西吗?

如果答案很容易适用于默认的Cygwin安装,那将会很棒。我想我可以尝试在cygwin上安装super-sed,但我想知道是否有更明显的想法

1 个答案:

答案 0 :(得分:2)

由于我目前没有可用的sed,并且从未实际使用过分组,因此该命令可能会起作用,也可能起作用(根本不起作用)=)

尝试

sed -r '/^COPY /{ s/([( ])(\w+)([,)])/\1"\U\2\E"\3/g }'

如果我正确理解了手册,这将在以COPY开头的任何行上执行替换。

另一种方法是使用分支。这看起来会复杂得多,但更灵活。