147

如何在一行中的模式之前插入换行符?

例如,这将在正则表达式模式后面插入一个换行符。

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

我怎么能在模式前面做同样的事情?

给定这个示例输入文件,要匹配的模式是电话号码。

some text (012)345-6789

应该成为

some text
(012)345-6789
4

17 回答 17

187

这适用于bashand zsh,在 Linux 和 OS X 上测试:

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

通常,for$后跟单引号中的字符串文字bash执行 C 样式的反斜杠替换,例如$'\t'被翻译为文字选项卡。另外, sed 希望你的换行文字用反斜杠转义,因此是\before $。最后,不应该引用美元符号本身,以便它被 shell 解释,因此我们在 the 之前关闭引用$,然后再次打开它。

编辑:正如@mklement0 评论中所建议的,这也有效:

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

这里发生的是:整个 sed 命令现在是一个 C 样式的字符串,这意味着 sed 需要放置在新行文字之前的反斜杠现在应该用另一个反斜杠转义。虽然更具可读性,但在这种情况下,您将无法进行 shell 字符串替换(不会再次使其变得丑陋。)

于 2012-06-22T20:05:35.287 回答
50

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

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

编辑:这似乎不适用于 OS X,除非您安装gnu-sed.

于 2009-04-06T21:06:07.637 回答
37

在 sed 中,您不能轻易在输出流中添加换行符。您需要使用续行,这很尴尬,但它有效:

$ sed 's/regexp/\
&/'

例子:

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

foo

有关详细信息,请参见此处。如果您想要稍微不那么尴尬的东西,您可以尝试使用perl -pe匹配组而不是 sed:

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

foo

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

于 2009-04-06T20:50:27.160 回答
31

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

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

这替换为换行符:

sed "s/regexp/\\`echo -e '\n\r'`/g"
于 2011-09-27T10:44:07.567 回答
16
echo one,two,three | sed 's/,/\
/g'
于 2012-12-01T10:30:49.097 回答
11

您可以像使用 sed 一样使用 perl 单行语句,并具有完整的perl 正则表达式支持的优势(这比使用 sed 获得的功能强大得多)。*nix 平台之间的差异也很小 - perl 通常是 perl。因此,您不必担心如何使您的特定系统版本的 sed 执行您想要的操作。

在这种情况下,你可以做

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

-pe将 perl 放入“执行和打印”循环中,很像 sed 的正常操作模式。

'引用其他所有内容,因此外壳不会干扰

()围绕正则表达式的是一个分组运算符。 $1在替换的右侧打印出这些括号内匹配的任何内容。

最后,\n是换行符。

无论您是否使用括号作为分组运算符,您都必须转义您尝试匹配的任何括号。因此,与您上面列出的模式匹配的正则表达式将类似于

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

\(or\)匹配一个文字括号,并\d匹配一个数字。

更好的:

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

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

此外,您可以为您的正则表达式使用除 / 以外的分隔符。所以如果你需要匹配 / 你不需要逃避它。以下任何一项都相当于我回答开头的正则表达式。理论上,您可以用 任何字符替换标准 / 的。

perl -pe 's#(regex)#\n$1#'
perl -pe 's{(regex)}{\n$1}'

几个最后的想法。

using-ne而不是-pe类似的行为,但不会在最后自动打印。如果您想自己打印,它会很方便。例如,这是一个类似 grep 的(m/foobar/是一个正则表达式匹配):

perl -ne 'if (m/foobar/) {print}'

如果您发现处理换行符很麻烦,并且希望为您神奇地处理它,请添加-l. 不过,对于使用换行符的 OP 来说没有用。

额外提示 - 如果您安装了 pcre 包,它会附带pcregrep,它使用完全兼容 perl 的正则表达式。

于 2014-05-21T17:44:38.537 回答
10

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

cat Somefile |tr ',' '\012' 

这需要逗号并将其替换为回车符。

于 2012-08-20T19:50:16.943 回答
4

嗯,刚刚转义的换行符似乎在更新的版本中工作sed(我有 GNU sed 4.2.1),

dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar
于 2014-05-21T20:35:31.487 回答
4
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

在 El Captitan 的()支持下运行良好

于 2015-12-10T15:40:38.710 回答
3

为了在 Linux 上的输出流中插入换行符,我使用了:

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

在哪里file1

def

在 sed 就地替换之前,并且:

abc
def

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

于 2012-09-14T20:02:01.200 回答
3

就我而言,以下方法有效。

sed -i 's/playstation/PS4/' input.txt

可以写成:

sed -i 's/playstation/PS4\nplaystation/' input.txt

PS4
游戏机

考虑在字符串文字中使用\\n时使用它。

  • sed : 是流编辑器

  • -i : 允许编辑源文件

  • +:是分隔符。

我希望以上信息对您有用。

于 2020-08-18T10:23:00.033 回答
2

在 sed 中,您可以使用“\1”、“\2”、...来引用模式中的组。因此,如果您要查找的模式是“PATTERN”,并且您想在其前面插入“BEFORE” ,你可以使用,没有转义

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

IE

  sed 's/\(PATTERN\)/BEFORE\1/g'
于 2009-04-06T20:50:51.480 回答
2
sed -e 's/regexp/\0\n/g'

\0是空值,因此您的表达式被替换为空值(无),然后...
\n是新行

在某些风格的 Unix 上不起作用,但我认为这是解决您问题的方法。

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow
于 2011-12-13T17:06:51.677 回答
2

您也可以使用 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
于 2016-07-28T08:32:25.293 回答
1

这适用于我的 MAC

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

Dono 是否是完美的...

于 2013-10-25T12:33:50.223 回答
1

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

#!/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

该脚本使用单个命令将换行符\n后跟另一行文本附加到文件末尾。sed

于 2016-01-25T13:34:51.840 回答
0

在 Red Hat 上的 vi 中,我能够仅使用 \r 字符插入回车。我相信这在内部执行“ex”而不是“sed”,但它是相似的,vi 可以是另一种进行批量编辑(例如代码补丁)的方式。例如。我用一个 if 语句包围了一个搜索词,该语句坚持在大括号后回车:

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

请注意,我还让它插入了一些标签以使事情更好地对齐。

于 2012-11-01T17:03:27.203 回答