ChatGPT解决这个技术问题 Extra ChatGPT

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

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

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

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

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

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

some text (012)345-6789

应该成为

some text
(012)345-6789
只需在此处重复 How do I insert a newline/linebreak after a line using sed 的答案:sed '/regex/G'
@NilsvonBarth,为什么一个简单的问题是一个坏问题?

m
mojuba

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

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

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

编辑:正如@mklement0 评论中所建议的那样,这也适用:

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

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


这给了我在 OSX 上的“替代模式内的未转义换行符”。
@Matt Gibson 这很奇怪,因为只有当您在替换模式中有一个没有反斜杠的真正换行符时才会给出“未转义换行符”。事实上,我上面的代码也可以在其他一些 shell 中工作,例如 zsh、ksh。
@Matt Gibson ...或者如果您在我的代码中忘记了 '$'\n 之前的反斜杠。
如所写,这些表达式完全用换行符替换了正则表达式,而不是按照要求在现有行的中间插入换行符。以下是我如何使用此答案的修改形式在两个匹配的模式之间插入换行符:sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'。注意 \n 后面的两个单引号。第一个关闭“$”部分,以便该行的其余部分不受它的影响。没有这些引号, \2 被忽略。
另一种选择是使用 single ANSI C-quoted string: sed $'s/regexp/\\\n/g',它可以提高可读性 - 唯一需要注意的是,您需要将所有文字 \ 字符 double
D
Dennis

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

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

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


我不确定这适用于所有版本的 sed。我在我的 Mac 上试过这个,\n 只是输出为 'n'
在阅读您的答案之前,我在 Mac 上花了 15 分钟。去苹果!
对于那些使用自制软件的人:brew install gnu-sed 后跟 gsed 's/regexp/\n&/g'
...随后是 echo 'alias sed=gsed' >> ~/.bashrc
T
Todd Gamblin

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

$ sed 's/regexp/\
&/'

例子:

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

foo

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

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

foo

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


为什么你说你不能添加换行符?你可以只做 sed 's/regexp/&\n/g' 就是这样
这是您在 Mac 上插入换行符时可以做的最不难看的事情(\n 在 Mac 上不起作用)
可以修改 perl 版本以进行就地编辑 perl -pi -e 's/(.*)/\n$1/' foo
@Andres:(大多数情况下)仅具有 POSIX 功能的 Sed 实现(例如 OS X 附带的 BSD 版本)不支持 s 函数调用的替换部分中的控制字符转义序列(与 GNU Sed 实现,确实如此)。上面的答案适用于两种实现;有关所有差异的概述,请参阅 here
R
Roar Skullestad

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

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

这替换为换行符:

sed "s/regexp/\\`echo -e '\n\r'`/g"

我正在执行内联编辑 sed -i '' -e ...,并且遇到了将 ^M 插入符号 M (ctrl+m) 写入文件的问题。我最终使用了具有相同参数的 perl。
请注意第二个代码插入了一个特殊的换行代码 LF CR(MS-DOS CR LF 的反转)!类 Unix 操作系统和 Mac OS X 都只使用 LF (\n)。
我的 sed 表达式中的其他东西引起了如此多的不快(尽管它在没有 echo... 和换行符的情况下工作正常),我只是在 vim 中这样做了。
或者简单地说:sed "s/regexp/`echo`/g" - 这将产生一个 LF 而不是 LF-CR
@mojuba:否:`echo` 将导致 空字符串,因为命令替换总是会修剪所有尾随换行符。没有办法使用命令替换来直接插入单个换行符(插入 \n\r - 即额外的 CR - 是一个糟糕的主意)。
g
gMale
echo one,two,three | sed 's/,/\
/g'

+1 工作完美,非常简单/易于记忆
这个答案实际上是一个 sed 解决方案,而不是一个 bash 解决方案。任何使用像 $'\n' 这样的结构的东西都依赖于 shell 来生成换行符。这样的解决方案可能不是便携的。这个是。当然,它也是 tgamblin 2009 年回答中第二个示例的副本。
这是在 Solaris 中唯一适用于我的版本。
D
Dan Pritts

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

在这种情况下,你可以做

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

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

' 引用其他所有内容,以便 shell 不会干扰

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

最后,\n 是换行符。

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

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

\(\) 匹配文字括号,而 \d 匹配数字。

更好的:

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

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

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

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

几个最后的想法。

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

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

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

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


u
user1612632

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

cat Somefile |tr ',' '\012' 

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


我发现这也有效:cat Somefile | tr ',' '\n' YMMV
g
gatoatigrado

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

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

如前所述,这适用于各种版本的 GNU sed,但不适用于 macOS 附带的 sed。
Q
Quanlong
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'

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


这很好用,你甚至可以给出一个完整的命令来测试和推断,以专门用于自己的目的。不错的工作!
S
Sicco

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

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

其中 file1 是:

def

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

abc
def

在 sed 就地替换之后。请注意 \\\n 的使用。如果模式中包含 ",请使用 \" 转义。


对我来说,上面的代码不起作用。 sed 插入 \n 而不是 LF,因为它从 shell 的参数中获取 \\n。 --- 此代码有效:sed -i "s/def/abc\ndef/" file1。 --- GNU sed version 4.2.1GNU bash, version 4.1.2(1) / 4.2.25(1)(CentOS 版本 6.4 / Ubuntu 12.04.3)。
v
vijayraj34

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

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

可以写成:

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

PS4游戏机

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

sed : 是流编辑器

-i : 允许编辑源文件

+:是分隔符。

我希望以上信息对你有用😃。


S
Steve B.

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

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

IE

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

刚刚做了:testfile contents="ABC ABC ABC"。运行 "sed 's/\(ABC\)/\n\1/g' 测试文件,得到换行符。尝试转义,尝试一次向您的模式添加 1 件事,例如,确保您匹配模式,然后检查组匹配,然后添加换行检查。
我刚刚试了一下,得到了“nABC nABC nABC”。你使用的是其他版本的 sed 吗?
外壳转义可能会妨碍 tgamblin 的尝试。像 Steve B 那样将完整的 sed 参数放在单引号中应该可以解决这个问题。尽管不同版本的 sed 可能不理解换行符的 \n 。
J
Jonathan Leffler

您也可以使用 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

1 在这里面做了什么?
@whatahitson 1 在 Awk 中用作 {print $0} 的简写。原因是任何计算结果为 True 的条件都会触发 awk 的默认操作,即打印当前记录。
s
slm
sed -e 's/regexp/\0\n/g'

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

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

echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow

l
laalto

这适用于我的 MAC

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

Dono 是否是完美的...


X
Xavier

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

#!/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 命令将换行符 \n 后跟另一行文本附加到文件的末尾。


R
Robert Casey

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

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

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