I would like to replace variations of a string using sed. The string pattern is required to match a set of optional repeatable characters ("../") and a mandatory string ("foo") For e.g. ../foo ../../foo ../../../foo
I can replace a single version such as ../../../foo using pattern which will yield using sed:
sed - 's/\.\.\/\.\.\/\.\.\/foo/foo1/'
=> foo1 but I want to extend to match any version so I get: ../foo => foo1 ../../foo => foo1 ../../../foo => foo1
How do I achieve this using sed?
CodePudding user response:
You can use
sed -E 's,(\.\./) foo,foo1,' file > newfile
Note the -E
option enables the POSIX ERE syntax and the (...)
are parsed as a grouping construct and
is parsed as a quantifier that matches one or more occurrences of the quantified subpattern.
If you need to make sure the match occurs at the start of the string, add ^
at the beginning: 's,^(\.\./) foo,foo1,'
. Note that the comma is used as a regex delimiter here to avoid escaping the /
char.
If the foo
must be matched as a whole word and if it ends with a word character, add \>
closing word boundary construct right after foo
.
See the online demo:
s='../foo
../../foo
../../../foo'
sed -E 's,(\.\./) foo,foo1,' <<< "$s"
Output:
foo1
foo1
foo1
CodePudding user response:
With awk
you could do it much easier form, just match the pattern and if its found then print the new value.
s='../foo
../../foo
../../../foo'
echo "$s" | awk 'match($0,/(\.\.) \/foo/){print "foo1"}'
Explanation: Simple explanation would be:
- First creating shell variable named
s
which has value of foo mentioned by OP in it. - Then printing its value by
echo
command and sending it as a standard input toawk
program. - In
awk
program, usingawk
'smatch
function to match regex(\.\.) \/foo
if mentioned regex matched then print new valuefoo2
in this case.
Explanation of regex:
(\.\.) \/foo
: match 2 literal dots(together) with 1 or more occurrences follows by /foo
if match found then print the new value.
Output will be as follows:
foo1
foo1
foo1