2

In sed how can I create a replacement string using a bash function, especially a function of one or more of the found parts, normally identified as \1, \2, ...?

In other words, I want to do something like this:

sed -e 's/\(.*\)/<bash_function \1>/'

Note: This Q is similar to How to embed a shell command into a sed expression?, but instead of calling a GNU/Linux command I want to simply call a local bash function.

Elliptical view
  • 3,921
  • 4
  • 27
  • 46

1 Answers1

5

You can do so with GNU sed, using the e flag:

e

This command allows one to pipe input from a shell command into pattern space. If a substitution was made, the command that is found in pattern space is executed and pattern space is replaced with its output. A trailing newline is suppressed; results are undefined if the command to be executed contains a NUL character. This is a GNU sed extension.

under the following restrictions:

  1. The entire resulting 'pattern space' (i.e. the entire input string after it's been searched and replaced) then gets executed, i.e. not just what's between the final two slashes. That's what you show in your example, but may not be what you actually want to do.

  2. your system's /bin/sh is bash

  3. you have exported the function, as described here Can I “export” functions in bash?

So for example on my system (where /bin/sh is the dash shell by default) the steps are

sudo ln -sf bash /bin/sh

foo() { echo "Doing foo on $1"; }
export -f foo

then I can do

$ echo bar | sed 's/\(.*\)/foo \1/e'
Doing foo on bar

Here's another example to further clarify that the entire input string after search and replace are performed is executed:

echo 'bar; echo xx' | sed 's/\(.*\)/foo \1/e'
Doing foo on bar
xx

If you can't arrange for /bin/sh to be bash, then probably the closest you will be able to get is to place the function definition in a file and source it first:

$ echo bar | sed 's/\(.*\)/foo \1/e'
sh: 1: foo: not found

but given

$ cat ./myfuncs.sh 
foo() { echo "Doing foo on $1"; }

then

$ echo bar | sed 's/\(.*\)/. .\/myfuncs.sh ; foo \1/e'
Doing foo on bar
Elliptical view
  • 3,921
  • 4
  • 27
  • 46
steeldriver
  • 81,074