0

i have a text file containing some content like that,

some content  
replace content  
other content

and i have some variables, looking like this:

PATH="/path/to/scriptdir"
PARAMETERS="para1 para2"
FILETOCHANGE="/foo/bar"

Now i want to replace the content in the text file that begins with replace, with the content of the variables PATH and PARAMETERS. The text file should look like that, after the replace:

some content
/path/to/scriptdir/script para1 para2
other content

I just tried the a couple of sed commands, but always i get an error. For example

sed -i "s/^replace.*$/$PATH/script $PARAMETERS/g" $FILETOCHANGE
sed: -e expression #1, char 12: unknown option to `s'

or

sed -i "s|^replace.*$|$PATH/script $PARAMETERS|g" $FILETOCHANGE
sed: -e expression #1, char 58: unterminated `s' command

Can you tell me, what I'm doing wrong?

  • 2
    It works for me. Note that $PATH is a special variable that contains paths to executable files, use $path isntead. – choroba Sep 27 '18 at 9:30
  • 1
    Your first attempt fails because the replacement ("$PATH") contains additional / characters. But your second should work, and with the values of PATH and PARAMETERS you've given, the resulting command should be less than 58 characters. Please can you confirm the actual values of these variables? – JigglyNaga Sep 27 '18 at 9:40
  • I confirm that using pipe | instead of backslash works. The issue is probably due to the fact that $PATH does not contain what you think. – francescop21 Sep 27 '18 at 9:49
  • @JigglyNaga I think you are right. I did some tests. My list of parameters is long. One parameter looks like /data/data/dir/more/scriptname and i have usually four parameters. I tested the command only with one parameter and it works. Do you know what i have to do, that my command can have more characters or do i have to split my command? – michaelgr Sep 27 '18 at 11:05
1

The ultimate solution is to switch from sed to Perl which handles variables as first class citizens, not as macros to expand as the shell does.

path=/path/to/scriptdir parameters="para1 para2" perl -i~ -pe \
    's|^replace.*$|$ENV{path}/script $ENV{parameters}|g' -- "$filetochange"
  • -p reads the input line by line and prints each line after processing it
  • the %ENV hash contains the environment variables, assigning to them at the beginning of a command makes them exported for the command
  • s/// (change the delimiters as you wish) works similarly to sed, see perlop
  • Thanks that works. I did some tests and i think now i know what that problem in my sed command was (see my comment above to JigglyNaga). With the perl code i don't have such limitations, that i have with my sed command and the long argument list. – michaelgr Sep 27 '18 at 11:17
1

(1) Do not use the variable PATH for this. It has a special meaning for the shell. I choose SCRIPTDIR here:

SCRIPTDIR="/path/to/scriptdir"
PARAMETERS="para1 para2"
FILETOCHANGE="/foo/bar"

(2) You do not need a slash (/) per se in sed's substitution command: s#this#that# or s|this|that| works as well as s/this/that/g. Sed just uses the character directly after the s as the separator for the rest of the s (substitute) command. You can use this to avoid the problem with the slashes in your pattern and replacement string: when you use e.g. | as a seperator, the slashes do not have any special meaning for sed.

So, this will work:

sed "s%^replace.*$%$SCRIPTDIR/script $PARAMETERS%g" $FILETOCHANGE

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.