【问题标题】:Selectively search and replace certain lines using a regular expression使用正则表达式有选择地搜索和替换某些行
【发布时间】:2011-02-24 14:44:32
【问题描述】:

我有一个包含很多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; 结尾的行。

我已经研究了前瞻/后瞻,但 sed 不支持它们。它们似乎在 super-sed 中受支持,但我目前使用的是 Cygwin(这里必须使用 Windows...),并且它似乎在软件包列表中不可用。

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

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

我是否遗漏了一些明显的东西?

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

【问题讨论】:

  • 鉴于您的示例,将 \w+ 替换为 [a-z]+ 会起作用,但它可能仍然对所有内容都不够选择性。
  • 你在这两种情况下都是对的!我举了一个简化的例子,但我真正担心的是不小心替换了COPY语句读取的一些数据,因为那里有很多数据......

标签: regex sed cygwin grep replace


【解决方案1】:

由于我目前没有可用的 sed,并且从未实际使用过分组,因此此命令可能有效也可能无效(完全或按预期)=)

试试

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

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

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

【讨论】:

  • 哇,非常感谢!这完美无缺。虽然这解决了我遇到的问题,但我对分支方法很好奇:它是否涉及对文件进行 grepping,查找“^COPY”,然后将结果“分支”到 sed 或标准输出?如何做到这一点? (也许将其发布在另一个答案中,以便人们也可以对其进行投票)
  • @eneveu:给你。我将此编辑为我的原始答案。不过,也未经测试。 sed 似乎是图灵完备的。吓人。
  • @Jens:我从你的第二个例子中得到一个错误:“sed: -e expression #1, char 9: unknown command: 'C'”
  • @Dennis:是的,我找到了。更正它。
  • @Jens:现在它给出:“sed:-e 表达式#1,字符 18:'s' 的未知选项”。提示:大多数有空格的地方应该是分号。第二条线索:您的“分支”版本没有做任何其他版本没有做的事情,除了不必要地进行空净效应替换。第一个示例中的选择器更简单、更直接。第三条线索:由于您的第一个替换锚定在行首,g 选项是无用的(并且不需要)。第四个线索:您可以在没有目标标签的情况下执行b,它会分支到最后。
猜你喜欢
  • 1970-01-01
  • 2013-06-14
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 2015-07-16
  • 1970-01-01
  • 2018-05-25
相关资源
最近更新 更多