I have a text file that looks like this


that I'm using to practice group capturing with regex and sed. The command I am running on the file (called test) is

sed 's/(?\(\d(3}\)[-.]?\(\d{3}\)[-.]?\(\d{4}\)/\1\2\3' test > output

Expecting the output that is just all 1's on every line. However, what I'm getting is just the entire file with no changes. What's going wrong?

  • 1
    ? needs backslash quoting. Apr 24, 2018 at 23:19
  • Thanks! That did not fix the problem however but now I know that was part of the problem.
    – RhythmInk
    Apr 24, 2018 at 23:23
  • It also neds a final /. Apr 25, 2018 at 0:11

3 Answers 3


In standard basic regex, (?\(\d(3}\)[-.]? means:

a literal left parenthesis
a literal question mark
(start of a group)
a literal character 'd'
a literal left parenthesis 
the number '3'
a literal closing brace
(end of group)
a dash or a dot
a question mark

i.e., this will print x:

echo '(?d(3}-?' |sed 's/(?\(\d(3}\)[-.]?/x/'

You're very likely to want sed -E to enable extended regular expressions (ERE), and to then use ( and ) for grouping, and \( and \) for literal parenthesis.

Also note that \d is part of Perl regexes, not standard ones, and while GNU sed supports some \X escapes, they're not standard (and I don't think it supports \d). Same for \?, GNU sed supports it in BRE to mean what ? means in ERE, but it's not standard.

With all that in mind:

$ echo '(123)-456-7890' | sed -E 's/\(?([0-9]{3})\)?[-.]?([0-9]{3})[-.]?([0-9]{4})/\1\2\3/'

Though you might almost as well just brute force it and just remove everything but the digits:

$ echo '(123)-456-7890' | sed -e 's/[^0-9]//g'

(that would of course also accept stuff like (123)-4.5-6-7a8b9c0...)

See also:

  • 1
    Good answer, just a tiny remark: According to the POSIX standard, the interpretation of an ordinary character preceded by an unescaped backslash is undefined, so while \d is likely to match a literal d, you can't rely on that.
    – Philippos
    Apr 25, 2018 at 6:31

We can do it below awk command too

echo "123-45-6789-10101"| awk '{gsub("[^0-9]","",$1);print }'



ilkkachu described very well why your regular expression does not work with sed (it's in a dialect not supported).

Here is an alternate way that just deletes the characters that are not 1:

sed 's/[^1]//g' file

To use groups, you may do something like

sed -E 's/([^1]*)(1+)([^1]*)/\2/g' file

That is, match a non-empty string of ones delimited on either side by a possibly empty string of non-ones, and replace all of that with the matched string of ones.

Change 1 to [0-9] and [^1] to [^0-9] to handle all digits.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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