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 '\/'

Jonik
  • 2,911
  • 4
  • 37
  • 48
  • 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 '13 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 '13 at 08:01

4 Answers4

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 (`\').
Kenny Rasschaert
  • 8,925
  • 3
  • 41
  • 58
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
user9517
  • 114,104
  • 20
  • 206
  • 289
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',
  }
robbyt
  • 1,622
  • 3
  • 14
  • 26
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!

Jonik
  • 2,911
  • 4
  • 37
  • 48