开发者

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

开发者 https://www.devze.com 2023-03-18 08:59 出处:网络
I want to use sed to modify my fil开发者_如何学Pythone named \"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

I want to use sed to modify my fil开发者_如何学Pythone named "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?

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


You can just use something like:

sed 's/foo/barfoo/g' baz

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

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

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

xyz fooA abc
xyz barfoo5 abc
xyz fooB abc

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

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\1/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 Diablo would give you three groups:

\1 = Pax Diablo
\2 = Pax
\3 = Diablo

as shown below:

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


Just substitute the start of the line with something different.

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


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.

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

In sed there 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

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号