Kit Ho
Kit Ho

Reputation: 26968

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

I want to use sed to modify my file 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

Upvotes: 12

Views: 64012

Answers (3)

paxdiablo
paxdiablo

Reputation: 881443

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]

Upvotes: 21

tripleee
tripleee

Reputation: 189387

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'

Upvotes: 0

Ignacio Vazquez-Abrams
Ignacio Vazquez-Abrams

Reputation: 798646

Just substitute the start of the line with something different.

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

Upvotes: 3

Related Questions