bash 如何使用 sed 命令在模式字符串之前添加一个字符串?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6619917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 20:44:18  来源:igfitidea点击:

How to use sed command to add a string before a pattern string?

bashsed

提问by Kit Ho

I want to use sed to modify my file named "baz".

我想使用 sed 来修改我的名为“baz”的文件。

When i search a pattern foo , foo is not at the beginning or end of line, i want to append bar before foo, how can i do it using sed?

当我搜索模式 foo 时,foo 不在行的开头或结尾,我想在 foo 之前附加 bar,我该如何使用 sed 来做到这一点?

Input file named baz:
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah
blah_foo_blahblahblah

Output file 
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah
blah_barfoo_blahblahblah

回答by paxdiablo

You can just use something like:

你可以使用类似的东西:

sed 's/foo/barfoo/g' baz

(the gat the end means global, every occurrence on each line rather than just the first).

g最后的意思是全局的,每一行上的每一次出现,而不仅仅是第一次出现)。

For an arbitrary(rather than fixed) pattern such as foo[0-9], you could use capture groups as follows:

对于任意(而不是固定)模式,例如foo[0-9],您可以按如下方式使用捕获组:

pax$ echo 'xyz fooA abc
xyz foo5 abc
xyz fooB abc' | sed 's/\(foo[0-9]\)/bar/g'

xyz fooA abc
xyz barfoo5 abc
xyz fooB abc

The parentheses capture the actual text that matched the pattern and the \1uses it in the substitution.

括号捕获与模式匹配的实际文本并\1在替换中使用它。

You can use arbitrarily complex patterns with this one, including ensuring you match only complete words. For example, only changing the pattern if it's immediately surrounded by a word boundary:

您可以将任意复杂的模式用于此模式,包括确保仅匹配完整的单词。例如,仅当它立即被单词边界包围时才更改模式:

pax$ echo 'xyz fooA abc
xyz foo5 abc foo77 qqq xfoo4 zzz
xyz fooB abc' | sed 's/\(\bfoo[0-9]\b\)/bar/g'

xyz fooA abc
xyz barfoo5 abc foo77 qqq xfoo4 zzz
xyz fooB abc


In terms of how the capture groups work, you can use parentheses to store the text that matches a pattern for later use in the replacement. The captured identifiers are based on the (characters reading from left to right, so the regex (I've left off the \escape characters and padded it a bit for clarity):

就捕获组的工作方式而言,您可以使用括号来存储与模式匹配的文本,以便以后在替换中使用。捕获的标识符基于(从左到右读取的字符,因此正则表达式(\为了清楚起见,我已经省略了转义字符并对其进行了填充):

( ( \S* )   ( \S* ) )
^ ^     ^   ^     ^ ^
| |     |   |     | |
| +--2--+   +--3--+ |
+---------1---------+

when applied to the text Pax Diablowould give you three groups:

当应用于文本时Pax Diablo,会给你三组:

 = Pax Diablo
 = Pax
 = Diablo

as shown below:

如下所示:

pax$ echo 'Pax Diablo' | sed 's/\(\(\S*\) \(\S*\)\)/[] [] []/'
[Pax Diablo] [Pax] [Diablo]

回答by Ignacio Vazquez-Abrams

Just substitutethe start of the line with something different.

只需用不同的东西替换行的开头。

sed '/^foo/s/^/bar/'

回答by tripleee

To replace or modify all "foo" except at beginning or end of line, I would suggest to temporarily replace them at beginning and end of line with a unique sentinel value.

要替换或修改除行首或行尾之外的所有“foo”,我建议将它们在行首和行尾临时替换为唯一的标记值。

sed 's/^foo/____veryunlikelytoken_bol____/
  s/foo$/____veryunlikelytoken_eol____/
  s/foo/bar&/g
  s/^____veryunlikelytoken_bol____/foo/
  s/____veryunlikelytoken_eol____$/foo/'

In sedthere is no way to specify "cannot match here". In Perl regex and derivatives (meaning languages which borrowed from Perl's regex, not necessarily languages derived from Perl) you have various negative assertions so you can do something like

sed没有办法来指定“无法比拟的在这里”。在 Perl 正则表达式和派生词(意思是从 Perl 的正则表达式借用的语言,不一定是从 Perl 派生的语言)中,您有各种否定断言,因此您可以执行以下操作

perl -pe 's/(?!^)foo(?!$)/barfoo/g'