使用 `sed` 替换表达式

使用 `sed` 替换表达式

我有一个包含许多语句的 SQL 文件INSERT,但它们都合并在一行上。我试图sed将它们分开在不同的行上,但我无法让它工作。这是我正在使用的命令:

sed 's/);INSERT/);\nINSERT/' myfile.sql

但是这个命令不起作用。它出了什么问题?我该如何修复它?

答案1

在正则表达式的末尾添加“g”来告诉它对所有匹配进行操作,而不仅仅是第一个找到的匹配。

sed 's/);INSERT/);\nINSERT/g' myfile.sql

答案2

该文件是从哪里来的?

如果是 Mac,分号后面可能有一个回车符(“\r”或 ASCII 0x13)。Mac 使用 CR 作为行分隔符,而 *nix 使用换行符,又称“换行符”(“\n”或 ASCII 0x0a)。

MS-Dos/Windows 使用两个字符序列 CR/LF(“\r\n”)来分隔行。

另外,如果输入只有一行,那么 s/search/replace/ 将只替换第一的在线匹配。您需要 g 修饰符来使其成为“全局”搜索和替换。

我猜测该文件来自 Mac,因为您说它只有一行……Windows 文件仍将被视为多行(因为 unix 可以看到一个 \n)。

尝试类似:

sed 's/);[\n\r]*INSERT/);\nINSERT/g' myfile.sql

这将与您的字符串在分号后立即匹配零个或多个 \n 和/或 \r 字符。还请注意 /g 修饰符。

如果失败了,我倾向于尝试 perl 而不是 sed(但我还是更喜欢 perl RE)。您可以将整个文件合并为标量字符串,并使用 /s 和 /g 修饰符来忽略行尾。您还可以使用 \R 字符类,它几乎可以匹配任何已知的行尾 - 根据 perlre 手册页,它匹配:

(?> \x0D\x0A?|[\x0A-\x0C\x85\x{2028}\x{2029}])

答案3

  • 插入 control-M 字符来代替 \n。在大多数现代 shell 中,您可以通过输入 control-V control-M 来执行此操作。
  • 另外,不要忘记 /g 以使更改全局应用于该行中的所有内容。

 sed 's/);INSERT/);^MINSERT/g' myfile.sql
                   |
                  control-V control-M

相关内容