1

I need to store some sed expressions in a variable and substitute it in the sed command.

myArgs="-e 's/foo/bar/' -e 's/foo2/bar2/'"

So far these are not working:

echo "foo" | sed ${myArgs} 
# sed: -e expression #1, char 1: unknown command: `''

echo "foo" | sed  $(echo ${myArgs})
# sed: -e expression #1, char 1: unknown command: `''

echo ${myArgs}
's/foo/bar/' -e 's/foo2/bar2/'
# 1st -e missing

Parameter expansion interprets the first -e argument in the variable.

-e may be interpreted as a test for exist, or argument to echo.

How can I prevent this and use it literally for the sed command?

To clarify, this is just a simplified version of a command that will contain a large number of sed expressions with characters that require escaping in the regex, and I would rather keep the expressions quoted as-is, and dump all the sed expressions into the sed command as a single variable.

If that's not possible, I'll use a different method such as the current answers below, however it seems there should be some built in bash method to not pre-expand the variable, and instead just interpret it as a string, before it's used in the final sed command.

The actual arguments I'm using will look something like this:

-e 's/^>chr1.*/>NC_032089.1_chr1/' -e 's/^>chr2.*/>NC_032090.1_chr2/'

With unknown strings

111
  • 1,788
  • 1
  • 23
  • 38

2 Answers2

4

Don't use a string, use an array:

myArgs=("-e" "s/foo/bar/" "-e" "s/foo2/bar2/")
sed "${myArgs[@]}" <<< "foo"
Poshi
  • 5,332
  • 3
  • 15
  • 32
  • Thanks. This is a simplified version of something I'm already trying to use, and I'd prefer not to have to refactor the other stuff if possible. – 111 May 08 '20 at 20:46
  • I ended up using a combination of both of the above answers however I'm accepting yours because the redirection was something I hadn't thought of – 111 May 08 '20 at 22:25
1

Since we know the input, and the sed code is safe enough, it's OK to use eval here:

echo foo | eval sed $myArgs

Output:

bar

Related Q. about things to be wary of: Why should eval be avoided in Bash, and what should I use instead?

Mo Budlong's Sunworld column Command line psychology 101 is the most helpful thing I've seen for understanding command line parsing.

agc
  • 7,973
  • 2
  • 29
  • 50
  • Thanks. The real input is unknown, and will contain other characters that could break eval. Eval could potentially work, but I was hoping there was some way to do the substitution without interpreting -e – 111 May 08 '20 at 21:28
  • 1
    Well, one might parse `$myArgs` in advance and quit if anything dangerous was found. The input (*e.g.* "foo" here) shouldn't matter. – agc May 08 '20 at 21:40