1

I am new to UNIX scripting and I am trying to use the sed command to replace text but I keep getting this error:

sed: -e expression #1, char 51: unknown option to `s'

Here is a snippet of the code that I have:

sed -e "/^#PBS -o ${rundir}/posttest/s#_CMODEL#${cmodel}#" \ -e "/^#PBS -e ${rundir}/posttest/s#_CMODEL#${cmodel}#" \ ${rundir}/run_post.shell >${rundir}/run_post.${cmodel}.sh 

Please let me know what I am doing wrong. Thanks a lot!!!

12
  • Does ${rundir} have / characters in it? Commented May 21, 2015 at 0:30
  • 2
    If you expect /^#PBS -o ${rundir}/posttest/ to be a regex pattern which indicates which lines the s command will apply to, then you need to escape the inner /. Otherwise, some explanation of what you are trying to do would be helpful. Commented May 21, 2015 at 0:31
  • @Barmar yes ${rundir} does have / in it does that change anything Commented May 21, 2015 at 0:34
  • You need to escape all the slashes in the regular expression, both the explicit one before posttest and the ones that are in the variable. Commented May 21, 2015 at 0:35
  • 1
    @alvits: good catch. But -[eo] is quite a bit easier on the eyes than -\(o\|e\), and \| is a Gnu sed extension which may not be available in all seds. Commented May 21, 2015 at 1:26

2 Answers 2

1

You need to escape the slashes in the regular expression that's being used as the address. Otherwise, the first slash will end the regexp, and the next character will be taken as a sed command to operate on those selected lines. You need to do this for both the slashes in $rundir and the slash that you have between ${rundir} and posttest.

For the variable, you can escape the slashes using bash's ${parameter/pattern/replacement} syntax, described here.

sed -e "/^#PBS -o ${rundir//\//\\/}\/posttest/s#_CMODEL#${cmodel}#" \ -e "/^#PBS -e ${rundir//\//\\/}\/s#_CMODEL#${cmodel}#" \ ${rundir}/run_post.shell >${rundir}/run_post.${cmodel}.sh 
Sign up to request clarification or add additional context in comments.

Comments

0

The problem is that the regular expression you are using as an address is terminated by the first /, which might be in ${rundir} or might be the / immediately following that; it is certainly not the / after posttest.

In general, interpolating variables into a regular expression is somewhat dangerous. If the variable's contents include regular expression metacharacters, then things are likely to fail in unexpected ways. If, as is the case here, the variable's value might include the regular expression terminator, then part of the variable's value will be interpreted as a command.

With that warning in mind, you have a couple of options. If you know that some character, say :, does not appear in ${rundir}, then you can use the that character as a regular expression terminator. (Note the backslash, which is how you tell sed that what follows is a regular expression.)

sed -e "\:^#PBS -o ${rundir}/posttest:s#_CMODEL#${cmodel}#" \ -e "\:^#PBS -e ${rundir}/posttest:s#_CMODEL#${cmodel}#" \ "${rundir}/run_post.shell" >"${rundir}/run_post.${cmodel}.sh" 

Alternatively, you could backslash-escape the literal / and use bash's pattern-substitution syntax to backslash-escape all the / in $rundir:

${rundir//\//\\/} 

(As mentioned above, you really should escape all possible metacharacters, including backslashes themselves.)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.