如何在一行中的模式之前插入换行符?
例如,这将在正则表达式模式后面插入一个换行符。
sed 's/regex/&\n/g'
我怎么能在模式前面做同样的事情?
给定这个示例输入文件,要匹配的模式是电话号码。
some text (012)345-6789
应该成为
some text
(012)345-6789
sed '/regex/G'
这适用于 bash
和 zsh
,在 Linux 和 OS X 上测试:
sed 's/regexp/\'$'\n/g'
通常,对于 $
后跟单引号中的字符串文字 bash
执行 C 样式的反斜杠替换,例如 $'\t'
被翻译为文字制表符。另外,sed 希望你的换行文字用反斜杠转义,因此 $
之前的 \
。最后,不应该引用美元符号本身,以便由 shell 解释它,因此我们关闭 $
之前的引号,然后再次打开它。
编辑:正如@mklement0 评论中所建议的那样,这也适用:
sed $'s/regexp/\\\n/g'
这里发生的是:整个 sed 命令现在是一个 C 样式的字符串,这意味着 sed 需要放置在新行文字之前的反斜杠现在应该用另一个反斜杠转义。虽然更具可读性,但在这种情况下,您将无法进行 shell 字符串替换(不会再次使其变得丑陋。)
其他一些答案不适用于我的 sed 版本。切换 &
和 \n
的位置确实有效。
sed 's/regexp/\n&/g'
编辑:这似乎不适用于 OS X,除非您安装 gnu-sed
。
brew install gnu-sed
后跟 gsed 's/regexp/\n&/g'
echo 'alias sed=gsed' >> ~/.bashrc
在 sed 中,您不能轻易在输出流中添加换行符。您需要使用续行,这很尴尬,但它有效:
$ sed 's/regexp/\
&/'
例子:
$ echo foo | sed 's/.*/\
&/'
foo
有关详细信息,请参阅 here。如果您想要稍微不那么尴尬的东西,您可以尝试将 perl -pe
与匹配组一起使用,而不是 sed:
$ echo foo | perl -pe 's/(.*)/\n$1/'
foo
$1
表示正则表达式中的第一个匹配组,其中组在括号中。
perl -pi -e 's/(.*)/\n$1/' foo
s
函数调用的替换部分中的控制字符转义序列(与 GNU Sed 实现,确实如此)。上面的答案适用于两种实现;有关所有差异的概述,请参阅 here。
在我的 Mac 上,以下内容插入一个 'n' 而不是换行符:
sed 's/regexp/\n&/g'
这替换为换行符:
sed "s/regexp/\\`echo -e '\n\r'`/g"
sed -i '' -e ...
,并且遇到了将 ^M
插入符号 M (ctrl+m) 写入文件的问题。我最终使用了具有相同参数的 perl。
\n
)。
echo...
和换行符的情况下工作正常),我只是在 vim 中这样做了。
sed "s/regexp/`echo`/g"
- 这将产生一个 LF 而不是 LF-CR
`echo`
将导致 空字符串,因为命令替换总是会修剪所有尾随换行符。没有办法使用命令替换来直接插入单个换行符(插入 \n\r
- 即额外的 CR - 是一个糟糕的主意)。
echo one,two,three | sed 's/,/\
/g'
$'\n'
这样的结构的东西都依赖于 shell 来生成换行符。这样的解决方案可能不是便携的。这个是。当然,它也是 tgamblin 2009 年回答中第二个示例的副本。
您可以像使用 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 的正则表达式。
在这种情况下,我不使用 sed。我用 tr。
cat Somefile |tr ',' '\012'
这需要逗号并将其替换为回车符。
cat Somefile | tr ',' '\n'
YMMV
嗯,刚刚转义的换行符似乎在 sed
的更新版本中工作(我有 GNU sed 4.2.1),
dev:~/pg/services/places> echo 'foobar' | sed -r 's/(bar)/\n\1/;'
foo
bar
echo pattern | sed -E -e $'s/^(pattern)/\\\n\\1/'
在 ()
支持下在 El Captitan 上运行良好
为了在 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.1
、GNU bash, version 4.1.2(1) / 4.2.25(1)
(CentOS 版本 6.4 / Ubuntu 12.04.3)。
就我而言,以下方法有效。
sed -i 's/playstation/PS4/' input.txt
可以写成:
sed -i 's/playstation/PS4\nplaystation/' input.txt
PS4游戏机
考虑在字符串文字中使用 \\n 时使用它。
sed : 是流编辑器
-i : 允许编辑源文件
+:是分隔符。
我希望以上信息对你有用😃。
在 sed 中,您可以使用“\1”、“\2”、...来引用模式中的组。因此,如果您要查找的模式是“PATTERN”,并且您想在其前面插入“BEFORE” ,你可以使用,没有转义
sed 's/(PATTERN)/BEFORE\1/g'
IE
sed 's/\(PATTERN\)/BEFORE\1/g'
您也可以使用 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
在 Awk 中用作 {print $0}
的简写。原因是任何计算结果为 True 的条件都会触发 awk 的默认操作,即打印当前记录。
sed -e 's/regexp/\0\n/g'
\0 是空值,因此您的表达式被替换为空值(无),然后... \n 是新行
在某些风格的 Unix 上不起作用,但我认为这是解决您问题的方法。
echo "Hello" | sed -e 's/Hello/\0\ntmow/g'
Hello
tmow
这适用于我的 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
命令将换行符 \n
后跟另一行文本附加到文件的末尾。
在 Red Hat 上的 vi 中,我能够仅使用 \r 字符插入回车。我相信这在内部执行“ex”而不是“sed”,但它是相似的,vi 可以是另一种进行批量编辑(例如代码补丁)的方式。例如。我用一个 if 语句包围了一个搜索词,该语句坚持在大括号后回车:
:.,$s/\(my_function(.*)\)/if(!skip_option){\r\t\1\r\t}/
请注意,我还让它插入了一些标签以使事情更好地对齐。
sed '\(first match\)\(second match\)/\1\'$'\n''\2/g'
。注意 \n 后面的两个单引号。第一个关闭“$
”部分,以便该行的其余部分不受它的影响。没有这些引号, \2 被忽略。sed $'s/regexp/\\\n/g'
,它可以提高可读性 - 唯一需要注意的是,您需要将所有文字\
字符 double。