Nick
Nick

Reputation: 4248

Conditional in perl regex replacement

I'm trying to return different replacement results with a perl regex one-liner if it matches a group. So far I've got this:

echo abcd |  perl -pe "s/(ab)(cd)?/defined($2)?\1\2:''/e"

But I get

Backslash found where operator expected at -e line 1, near "1\"
(Missing operator before \?)
syntax error at -e line 1, near "1\"
Execution of -e aborted due to compilation errors.

If the input is abcd I want to get abcd out, if it's ab I want to get an empty string. Where am I going wrong here?

Upvotes: 4

Views: 1517

Answers (3)

ikegami
ikegami

Reputation: 385565

You used regex atoms \1 and \2 (match what the first or second capture captured) outside of a regex pattern. You meant to use $1 and $2 (as you did in another spot).

Further more, dollar signs inside double-quoted strings have meaning to your shell. It's best to use single quotes around your program[1].

echo abcd | perl -pe's/(ab)(cd)?/defined($2)?$1.$2:""/e'

Simpler:

echo abcd | perl -pe's/(ab(cd)?)/defined($2)?$1:""/e'

Simpler:

echo abcd | perl -pe's/ab(?!cd)//'

  1. Either avoid single-quotes in your program[2], or use '\'' to "escape" them.
  2. You can usually use q{} instead of single-quotes. You can also switch to using double-quotes. Inside of double-quotes, you can use \x27 for an apostrophe.

Upvotes: 6

user557597
user557597

Reputation:

And a couple of even better ways

Find abcd(*SKIP)(*FAIL)|ab
Replace ""

Find (?:abcd)*\Kab
Replace ""

These use regex wisely.
There is really no need nowadays to have to use the eval form
of the regex substitution construct s///e in conjunction with defined().
This is especially true when using the perl command line.

Good luck...

Upvotes: 0

user557597
user557597

Reputation:

Why torture yourself, just use a branch reset.

Find (?|(abcd)|ab())
Replace $1

Upvotes: 0

Related Questions