58

I am using sed in a shell script to edit filesystem path names. Suppose I want to replace

/foo/bar

with

/baz/qux

However, sed's s/// command uses the forward slash / as the delimiter. If I do that, I see an error message emitted, like:

▶ sed 's//foo/bar//baz/qux//' FILE
sed: 1: "s//foo/bar//baz/qux//": bad flag in substitute command: 'b'

Similarly, sometimes I want to select line ranges, such as the lines between a pattern foo/bar and baz/qux. Again, I can't do this:

▶ sed '/foo/bar/,/baz/qux/d' FILE
sed: 1: "/foo/bar/,/baz/qux/d": undefined label 'ar/,/baz/qux/d'

What can I do?

Braiam
  • 1
  • 11
  • 47
  • 78
DerZauberer
  • 595
  • 1
  • 4
  • 9
  • `sed statement <<< cat` – geirha Nov 25 '15 at 21:50
  • @geirha not sure what you mean here. – fedorqui Nov 25 '15 at 23:17
  • Try `sed 'sahanag' <<< "haha"`. In your aaa's example it fails only because the regex is blank and your either branching to an unlabeled a location, and the g command needs to be segregated with a semicolon - or - you are branching to an unlabeled ag location. You can also use unprintable characters to delimit such as `SOH $'\001'`. You can see an working example here: https://github.com/AdamDanischewski/gen-uniq-id/blob/master/gen_uniq_id.bsh –  Nov 26 '15 at 20:31
  • Does this answer your question? [How to pass a variable containing slashes to sed](https://stackoverflow.com/questions/27787536/how-to-pass-a-variable-containing-slashes-to-sed) – tripleee Sep 25 '20 at 09:33
  • But then on the other hand the answer here is rather spare. Perhaps they should be merged. – tripleee Dec 17 '21 at 08:49
  • @tripleee yeah, that could work. Just showing my preference for this one because it has a better SEO (33K visits in 5y, while the other 22K in 10y) – fedorqui Dec 17 '21 at 09:30

3 Answers3

94

You can use an alternative regex delimiter as a search pattern by backslashing it:

sed '\,some/path,d'

And just use it as is for the s command:

sed 's,some/path,other/path,'

You probably want to protect other metacharacters, though; this is a good place to use Perl and quotemeta, or equivalents in other scripting languages.

From man sed:

/regexp/
Match lines matching the regular expression regexp.

\cregexpc
Match lines matching the regular expression regexp. The c may be any character other than backslash or newline.

s/regular expression/replacement/flags
Substitute the replacement string for the first instance of the regular expression in the pattern space. Any character other than backslash or newline can be used instead of a slash to delimit the RE and the replacement. Within the RE and the replacement, the RE delimiter itself can be used as a literal character if it is preceded by a backslash.

Sundeep
  • 23,246
  • 2
  • 28
  • 103
geekosaur
  • 59,309
  • 11
  • 123
  • 114
  • And to use a different delimiter for a start and ending search pattern a la `/foo/,/bar/`, use `sed '\=some/path=,\=other/path='`. Notice you have to repeat the escape character \ at the beginning of the 2nd search pattern. Obvious if you think about it, but it puzzled me a moment. – Stefan van den Akker Aug 16 '23 at 09:39
46

Perhaps the closest to a standard, the POSIX/IEEE Open Group Base Specification says:

[2addr] s/BRE/replacement/flags

Substitute the replacement string for instances of the BRE in the pattern space. Any character other than backslash or newline can be used instead of a slash to delimit the BRE and the replacement. Within the BRE and the replacement, the BRE delimiter itself can be used as a literal character if it is preceded by a backslash."

fedorqui
  • 275,237
  • 103
  • 548
  • 598
JCx
  • 2,689
  • 22
  • 32
-2

When there is a slash / in theoriginal-string or the replacement-string, we need to escape it using \. The following command is work in ubuntu 16.04(sed 4.2.2).

sed 's/\/foo\/bar/\/baz\/qux/' file
wangloo
  • 27
  • 7