3

In a config file, I'm trying to replace PREFIX=/jenkins with, say, PREFIX=/foobar.

On the (bash) command line, this works fine:

sed -i.bak s/PREFIX=\\/jenkins/PREFIX=\\/foobar/g /etc/default/jenkins

However, in a Puppet script (.pp file):

exec { 'Change-prefix':
  command => "sed -i.bak s/PREFIX=\\/jenkins/PREFIX=\\/foobar/g /etc/default/jenkins",
  path    => ["/bin"],
}

produces:

err: /Stage[main]//Exec[Change-prefix]/returns: change from notrun to 0 failed:
sed -i.bak s/PREFIX=\/jenkins/PREFIX=\/foobar/g /etc/default/jenkins 
returned 1 instead of one of [0] 

How to escape the sed command properly? Or is something else the matter?

I also tried with \\\/, but that yields: warning: Unrecognised escape sequence '\/'

2
  • 2
    It may be a better idea to let Puppet manage the whole /etc/default/jenkins file using a template, than to rely on an exec calling sed.
    – daff
    Mar 11, 2013 at 12:35
  • @daff: Yes, probably... But for my simple needs, for now, this suffices (and I'm not really familiar with Puppet templates yet). Later on I might change it to a more idiomatic Puppet approach.
    – Jonik
    Mar 12, 2013 at 8:01

4 Answers 4

4

In cases where your sed expression contains a '/', you may want to consider using a different delimiter. I chose the pipe symbol in this example.

sed -i.bak 's|PREFIX=/jenkins|PREFIX=/foobar|g' /etc/default/jenkins

Using this syntax in your Puppet manifest would be a lot cleaner and more readable, in my opinion.


From the sed info page:

\%REGEXP%' (The%' may be replaced by any other single character.)

 This also matches the regular expression REGEXP, but allows one to
 use a different delimiter than `/'.  This is particularly useful
 if the REGEXP itself contains a lot of slashes, since it avoids
 the tedious escaping of every `/'.  If REGEXP itself includes any
 delimiter characters, each must be escaped by a backslash (`\').
1
  • This was new to me, but yes, it's a lot cleaner this way. Thanks (to both answerers)!
    – Jonik
    Mar 11, 2013 at 12:39
4

On many versions of sed you can use a different character as a delimiter to avoid having to escape / e.g it's quite common to use | or #

sed -i.bak 's#PREFIX=/jenkins#PREFIX=/foobar#g' /etc/default/jenkins
3

Whoa, whoa... hang-on! Sed in a puppet manifest is a bit crazy. You should be using the file_line resource, from the puppetlabs stdlib.

(you should install the entire module, but here is the custom resource type) https://github.com/puppetlabs/puppetlabs-stdlib/blob/master/lib/puppet/type/file_line.rb

Example:

  file_line { 'sudo_rule':
    path => '/etc/sudoers',
    line => '%sudo ALL=(ALL) ALL',
  }
1
  • Thanks! file_line together with match attribute is exactly what did the job!
    – Laas
    Jun 11, 2014 at 15:43
1

Turns out \\\\/ works.

For example:

exec { 'Change-prefix':
  command => "sed -i.bak s/PREFIX=\\\\/jenkins/PREFIX=\\\\/foorbar/g /etc/default/jenkins",
  path    => ["/bin"],           
}

Edit: ...but of course using a different delimiter, as Kenny and Iain suggested, is a lot cleaner solution!

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .