Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Assume you have a text file:

foo fnord bar
bizz foo poit

And now I would want to replace both "foo" and "bar" into "narf".

I know I could use:

 sed -e 's/foo/narf/g' -e 's/bar/narf/g' fileName

Yet I would like to work with an OR-operator that tells the regex to match both needles via one expression.

Hitting some manuals I suppose the pipe should fit my needs but I tried

sed -e 's/foo|bar/narf/g' -i fileName

and it didn't work and it's not even throwing an error.

What am I doing wrong here?

share|improve this question
add comment

2 Answers

up vote 6 down vote accepted

Use -r option for extended regexp syntax:

sed -r -e 's/foo|bar/narf/g'

Otherwise escape the disjunction as \|:

sed -e 's/foo\|bar/narf/g'
share|improve this answer
add comment

There are many variations on regular expression syntax. The very first tools in the unix world that had regular expressions did not have the full capabilities of regular expressions, only character sets ([…] and .), repetition (*) and line anchors (^ and $). Basic regular expressions only have these operators. Sed is an old-school tool and uses basic regexps.

Many sed implementations have extensions for full regexp matching. Because the character | stands for itself, you need to use \| for alternation, and similarly \( and \) for grouping. Note that the POSIX standard does not mandate that \| be supported in basic regular expressions, and some systems (e.g. OpenBSD) do not have it.

Some versions of sed have an option to switch to extended regular expressions, where (…) is used for grouping and | for alternation. With GNU sed (i.e. under Linux or Cygwin) or Busybox, pass the -r option. On FreeBSD or OSX, pass the -E option.

If your sed does not have alternation, you can call awk instead. It's mandated by POSIX, but a bit verbose for this task, and it does not support backreferences.

awk '{gsub(/foo|bar/, "narf")}' <fileName.old >fileName.new

By the way, only GNU and Busybox sed support file replacement in place. Awk and other versions of sed don't. See Can I make `cut` change a file in place?

If you have Perl, it's often handy in a one-tool-does-all kind of way for text processing one-liners. Most of what's easy in sed, awk and the rest isn't much more difficult in Perl, and you can get away with learning a single (if complex) tool.

perl -i -pe 's/foo|bar/narf/g' fileName
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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