用`sed`replaceexpression式

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

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

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

在正则expression式的末尾添加一个“g”,告诉它在所有匹配上工作,而不是仅仅find第一个匹配。

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

文件从哪里来的?

如果是Mac,那么在分号后面可能会出现回车符(“\ r”或ASCII 0x13)。 Mac使用CR作为行分隔符,而* nix使用换行符(又名“换行”(“\ n”或ASCII 0x0a))。

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

另外,如果input全部是一行,那么s / search / replace /将只replace行上的第一个匹配。 您需要使用g修饰符来使其成为“全局”search和replace。

我的猜测是,该文件是从Mac,因为你说这只是一行…一个Windows文件仍然会被视为多行(因为有一个\ n为unix看到)。

尝试像这样:

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

这将匹配您的string与紧接在分号后面的零个或多个\ n和/或\ r个字符。 还要注意/ g修饰符。

如果失败了,我会倾向于尝试perl而不是sed(但是我更喜欢perl RE)。 你可以把整个文件写成一个标量string,并使用/ s和/ g修饰符几乎忽略行尾。 你也可以使用\ R字符类匹配几乎任何已知的行结尾 – 根据perlre手册页,它匹配:

(> \ X0D \ X0A |?[\ x0A- \ X0C \ X85 \ X {2028} \ X {2029}])

  • 插入一个控制-M字符,而不是\ n。 您可以通过键入control-V control-M在大多数现代shell中执行此操作。
  • 另外,请不要忘记/ g将更改全局化为行中的所有内容。

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