0

I want to replace a? with b? where ? is a character, not a wildcard. Here is what I tried:

 echo "a?c" | sed 's/a\?/b?/'

I expect b?c, but it returns b??c. I also tried two backslashes between a and ?, it doesn't work either.

3
  • 1
    echo "a?c" | sed 's/a?/b?/'? Commented Apr 19 at 6:56
  • interesting, isn't ? a wildcard in regex? Commented Apr 19 at 7:02
  • 2
    It is, but interestingly escaping is reversed to what we are used from other regex dialects. Ie to match "zero or one" you have to use \? and ? alone matches literally a question mark. Ie a\? matches "zero or one instances of the letter a" and doesn't care about the following ? gnu.org/software/sed/manual/html_node/Regular-Expressions.html Commented Apr 19 at 7:08

3 Answers 3

5

When not inside a bracket expression, the interpretation of an ordinary character preceded by an unescaped <backslash> is undefined, except for:

[...]

  • The '?', '+', and '|' characters; it is implementation-defined whether "\?", "\+", and "\|" each match the literal character '?', '+', or '|', respectively, or behave as described for the ERE special characters '?', '+', and '|', respectively (see 9.4.3 ERE Special Characters).

Note: A future version of this standard may require "\?", "\+", and "\|" to behave as described for the ERE special characters '?', '+', and '|', respectively.

https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html#tag_09_03_02

When BRE is being used, to avoid ? being treated as an ERE special character in implementations where \ turns it into one, don't use the backslash.

For portability, if you want to use ERE, invoke sed with the -E flag which allows use of ? to mean zero-or-one and where escaping it with backslash has the effect you were expecting. (The BRE equivalent of ERE ? is \{0,1\}.)

To avoid ? being treated as a metacharacter in either flavour, regardless of implementation, use a bracket expression: [?]

Sign up to request clarification or add additional context in comments.

Comments

0

With Sparrow/Raku it is quite simple:

task.bash

#!bash
echo "a?c"
echo "a?d"
echo "a?f"

task.check

# find all strings with "a?"
a?

code: <<HERE
!raku

for matched()<> -> $l {
  say $l.subst("a?","b?",:g)
}
HERE

Example output

s6 --task-run .
22:48:34 :: [sparrowtask] - run sparrow task .
22:48:34 :: [sparrowtask] - run [.], thing: .
[task run: task.bash - .]
[task stdout]
22:48:35 :: a?c
22:48:35 :: a?d
22:48:35 :: a?f
[task check]
stdout match <a?> True
# b?c
# b?d
# b?f

Comments

0

multiple standards

Regular Expressions are so difficult to write that you shouldnt have to write a slightly different one for every language. The partial solution to this problem is to use PCRE or Perl Compatible Regular Expressions.

Grep supports PCRE with the -P option as well as most major languages. However sed does not, even though there was once apparently something in the works. In my opinion Perl is superior to grep sed and awk in nearly every way. So the best option would probably be to just use Perl. You would not have to learn all the different wrinkles in syntax, and your regular expressions would be portable across any language that supports PCRE.

For this and many other reasons, Perl is a perfect drop in replacement for comparable languages and tools, and your original regular expression would have worked unaltered. Try something like this...

$ echo "a?c" | perl -pe 's/a\?/b\?/'
b?c

The -p option tells Perl to loop over each line of input, and print the result at the end of each line. In case you wanted to do something like this...

$ ls | perl -pe 's/a\?/b\?/'

The -e option says the entire program is on the command line instead of in a file. If you pipe input into Perl using the | operator, Perl will loop over the text of each line. But if you use regular command line arguments, Perl will assume they are files, open each file, and process them line by line. Similar to running grep with command line arguments.

With a little time and effort, you will find Perl invaluable. The syntax is very stable, supported on every platform, and Perl is just all around much more powerful and versatile than comparable tools.

7 Comments

There's another related cartoon at zoitz.com/comics/perl_small.png. PCREs aren't part of the POSIX standard and no version of the mandatory POSIX tools (i.e. available on all Unix boxes) sed and awk support PCREs, only the GNU version of grep does and that has caveats, so saying "supported on every platform" is incorrect. After programming in Unix for over 40 years I still haven't found a use for perl. Since we're giving opinions - if you're OK with a non-standard tool them python is much more useful and doesn't have perls write-only code reputation.
I'll take PCRE over POSIX any day of the week. Many languages support PCRE's although sed and awk dont, but they are considered tools, not complete languages like Perl. Perl will be a more powerful and versatile drop in replacement in either case. PCRE's are supported on every platform, which is technically every operating system that has a Perl interpreter. Which is close to all of them. But PCRE's are also supported on the web, the command line, and in C/C++. If you wanted to use PCRE's instead of flavor of the month Regular Expressions, you could. No matter what you were writing.
I spent most of my career working on platforms that only have POSIX tools available and we see questions posted here and on SE by people who also only have POSIX tools available so claims of PCRE and/or perl general availability are exaggerated.
Small systems based around busybox support ERE but installing Perl on them may be impractical. A BangleJS watch can run JavaScript code, whose regex syntax is borrowed from Perl, but again installing Perl would be infeasible. Many people try to minimise the size of their docker images - they don't want to install an entire Perl ecosystem for a few simple commands. etc
@user3408541 it's exactly what I said. Just because it is physically possible for people to install tools on Unix that support PCREs doesn't mean the product you are working on is allowed to have such tools installed on it. You are confusing what you can do at home with what you can do in any given work environment.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.