47

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?

fedorqui
  • 252,262
  • 96
  • 511
  • 570
DerZauberer
  • 485
  • 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
  • the real question is which delimiter is THE BEST – CervEd Dec 16 '21 at 21:03
  • 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

2 Answers2

76

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
  • 21,380
  • 2
  • 23
  • 85
geekosaur
  • 56,235
  • 11
  • 119
  • 111
44

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
  • 252,262
  • 96
  • 511
  • 570
JCx
  • 2,562
  • 19
  • 32