如何在模式前插入换行符?

不是如何在一行之前插入换行符。 这是问如何在行内的模式之前插入换行符。

例如,

sed 's/regexp/&\n/g' 

将在正则expression式模式后插入一个换行符。

我怎样才能做到这一点,但在模式之前?

这是一个示例input文件

 somevariable (012)345-6789 

应该成为

 somevariable (012)345-6789 

这在bash ,在Linux和OS X上testing:

 sed 's/regexp/\'$'\n/g' 

一般情况下,对于$后接单引号中的string, bash执行C型反斜杠replace,例如$'\t'被转换为文字标签。 另外,sed希望你的新行文字能够用反斜杠转义,因此在$之前。 最后,美元符号本身不应被引用,以便它被shell解释,因此我们在$之前closures引号,然后再打开它。

编辑 :正如在@ mklement0的评论中所build议的,这也是一样的:

 sed $'s/regexp/\\\n/g' 

这里发生的事情是:整个sed命令现在是一个C风格的string,这意味着sed需要放置的反斜线现在应该用另一个反斜杠转义。 虽然更具可读性,但在这种情况下,您将无法执行shellstringreplace(不会再使其变丑)。

一些其他的答案不适用于我的版本的sed。 切换&\n的位置确实有效。

 sed 's/regexp/\n&/g' 

编辑:这似乎无法在OS X上工作,除非你安装gnu-sed

在sed中,您不能轻易地在输出stream中添加换行符。 你需要使用延续线,这是尴尬的,但它的工作原理:

 $ sed 's/regexp/\ &/' 

例:

 $ echo foo | sed 's/.*/\ &/' foo 

详情请看这里 。 如果你想要一些稍微笨拙的东西,你可以尝试使用perl -pe与match组而不是sed:

 $ echo foo | perl -pe 's/(.*)/\n$1/' foo 

$1是指正则expression式中的第一个匹配组,其中组在圆括号中。

在我的Mac上,下面插入一个'n'而不是换行符:

 sed 's/regexp/\n&/g' 

这取代换行符:

 sed "s/regexp/\\`echo -e '\n\r'`/g" 
 echo one,two,three | sed 's/,/\ /g' 

在这种情况下,我不使用sed。 我用tr。

 cat Somefile |tr ',' '\012' 

这需要逗号并用回车代替它。

嗯,刚刚逃脱换行似乎在更新的版本的sed (我有GNU sed 4.2.1),

 dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;' foo bar 

您可以像使用sed一样使用perl单行程序,并具有完整的perl正则expression式支持(比sed更强大)。

此外,* nix平台上的变化很小 – perl通常是perl。 所以你可以不用担心如何让你的特定系统的sed版本做你想要的。

在这种情况下,你可以做

 perl -pe 's/(regex)/\n$1/' 

-pe使perl进入“执行和打印”循环,就像sed的正常操作模式一样。

'引用其他所有内容,因此shell不会干涉

()围绕正则expression式是一个分组操作符。 在replace的右侧$1打印出这些parens里面匹配的东西。

最后, \n是换行符。

无论您是否使用圆括号作为分组操作符,您都必须转义您尝试匹配的括号。 所以一个正则expression式匹配你上面列出的模式将是类似的

 \(\d\d\d\)\d\d\d-\d\d\d\d 

\(\)匹配文字paren, \d匹配一个数字。

更好:

 \(\d{3}\)\d{3}-\d{4} 

我想你可以弄清楚大括号里的数字在做什么。

奖金提示 – 如果您已经安装了pcre软件包,它将附带pcregrep ,它使用完整的perl兼容正则expression式。

为了在Linux上插入一个换行符输出stream,我使用了:

 sed -i "s/def/abc\\\ndef/" file1 

其中file1是:

 def 

在sed就地更换之前,以及:

 abc def 

在sed就地更换后。 请注意使用\\\n 。 如果模式有一个"在里面,使用\"转义。

在sed中,您可以使用“\ 1”,“\ 2”,…引用组中的组,所以如果您要查找的模式是“PATTERN”,并且想要在其前面插入“BEFORE” ,你可以使用,无sans逃脱

 sed 's/(PATTERN)/BEFORE\1/g' 

  sed 's/\(PATTERN\)/BEFORE\1/g' 
 sed -e 's/regexp/\0\n/g' 

\ 0是空的,所以你的expression被replace为空(没有),然后…
\ n是新行

在一些Unix的口味不起作用,但我认为这是你的问题的解决scheme。

 echo "Hello" | sed -e 's/Hello/\0\ntmow/g' Hello tmow 
 echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/' 

在El Captitan ()支持下工作得很好

你也可以用awk来做到这一点,使用-v来提供模式:

 awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file 

这将检查一行是否包含给定的模式。 如果是这样,它会在它的开头附加一个新行。

看一个基本的例子:

 $ cat file hello this is some pattern and we are going ahead bye! $ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' file hello this is some pattern and we are going ahead bye! 

注意它会影响到一行中的所有模式:

 $ cat file this pattern is some pattern and we are going ahead $ awk -v patt="pattern" '$0 ~ patt {gsub(patt, "\n"patt)}1' d this pattern is some pattern and we are going ahead 

在Red Hat上的vi中,我只能使用\ r字符插入回车符。 我相信这在内部执行“ex”而不是“sed”,但它是相似的,vi可以是另一种批量编辑的方法,如代码补丁。 例如。 我围绕着一个search词,用一个if语句来坚持​​大括号之后的回车:

 :.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/ 

请注意,我也有它插入一些标签,使事情更好地alignment。

这在MAC中适用于我

 sed -i.bak -e 's/regex/xregex/g' input.txt sed -i.bak -e 's/qregex/\'$'\nregex/g' input.txt 

Dono是否是完美的…

在阅读了这个问题的所有答案之后,我仍然花了很多的尝试去获得下面的示例脚本的正确语法:

 #!/bin/bash # script: add_domain # using fixed values instead of command line parameters $1, $2 # to show typical variable values in this example ipaddr="127.0.0.1" domain="example.com" # no need to escape $ipaddr and $domain values if we use separate quotes. sudo sed -i '$a \\n'"$ipaddr www.$domain $domain" /etc/hosts 

该脚本使用单个sed命令将换行符追加到另一行文本的后面。

由于OS X上的高级replace可能会模糊,因此我使用了php作为此选项,因为它可以通过选项-r直接从CLI调用:

 php -r 'str_replace("pattern", "\npattern");' 

此外,PHP可以传递参数,所以它完美地集成在高级脚本中。 这里有一个更强大的例子,embedded在一个bash脚本中的PHP将直接在文件中进行replace:

 pattern=xxx php -r '$filePath = "/home/buzut/file"; file_put_contents($hostsFilePAth, str_replace($argv[1], "\n$argv[1]", file_get_contents($filePath)));' $pattern