-3

I have a file -

cat regex30.txt 
(914).582.3013
(873).334.2589
(521).589.3147
(625).235.3698
(895).568.2145
(745).256.3369

I want to convert this to

914.582.3013
873.334.2589
521.589.3147
625.235.3698
895.568.2145
745.256.3369

Here are my steps -

sed -r 's/\(([0-9]<Space>{3})\)(\.[0-9]{3}\.[0-9]{4})/\1\2/g' regex30.txt 

then I get the result -

(914).582.3013
(873).334.2589
(521).589.3147
(625).235.3698
(895).568.2145
(745).256.3369

Why I get that result? How come space matters there?

If I remove space then it works correctly.

sed -r 's/\(([0-9]{3})\)(\.[0-9]{3}\.[0-9]{4})/\1\2/g' regex30.txt 
914.582.3013
873.334.2589
521.589.3147
625.235.3698
895.568.2145
745.256.3369

My understanding is that [0-9] {3} -- means 3 digit numbers, it can start with zero as well.

What is the difference between [0-9]{3} and [0-9] {3} in RegEx?

Why space matters there or is it something I am unable to see all together.

I thought '\s' is used to represent spaces.

3
  • 3
    Space is also a token in regular expression. That's why no substitution is done, as you provided the information. – tail spark rabbit ear Jan 25 at 6:23
  • 1
    If you just want to delete parentheses, use tr -d '()' <indata, – Kusalananda Jan 25 at 9:58
  • I thought /s is used to represent space. – tannoy connect Jan 25 at 23:26
4

Disclaimer: I did not try to parse your regular expression. Here is the answer to your question.

[0-9]{3} means exactly three decimal digits. [0-9] {3} means a single decimal digit followed by exactly three spaces. This is so because {3} (which is a so-called "bound") repeats the so-called "atom" preceding it.

From the regex manual page:

$ man regex
... An atom followed by a bound containing one integer i and no comma 
matches a sequence of exactly i matches of the atom. ...

The term "atom" is defined in the following paragraph. Great reading.

7
  • 5
    Technically, [0-9] is 3 collating elements that sort in between 0 and 9. While that includes ASCII decimal digit characters, in several sed implementations (including GNU sed) and some locales, that includes a lot more. – Stéphane Chazelas Jan 25 at 6:32
  • @Stéphane so GNU treats [0-9] as being equivalent to [[:digit:]]? Meaning that if I really want just Latin digits I have to write an ERE such as (0|1|3|...|9)? Or would forcing the C locale be sufficient still? – roaima Jan 25 at 9:32
  • 1
    @roaima, no [[:digit:]] is meant to match on [0123456789] though in practice on some systems (not GNU AFAIK) it matches on other decimal digits (in other numeral systems). [0-9] can match on things that are not digits, they just need to sort in between 0 and 9. That could be for instance 🆛 or 🆡. It's also likely not to include digits 9 in other numeral systems/scripts as they would likely come after ASCII 9. – Stéphane Chazelas Jan 25 at 9:43
  • @StéphaneChazelas thank you – roaima Jan 25 at 10:05
  • @roaima, in the C locale [0-9] and [0123456789] are equivalent but changing LC_CTYPE to C changes the way sequences of bytes are interpreted into characters. In some charsets, the encoding of 0-9 also appear as part of some other characters so LC_ALL=C grep '[0-9]' could for instance match inside some characters if the input was encoded in charsets such as GB18030 (the charset used in some Chinese locales) for instance. – Stéphane Chazelas Jan 25 at 10:32
1

The only regexps that I know where white space can be ignored are the perl ones or compatible and the ast-open ones (which did borrow many operators from perl regexps), though that's not done by default, only when the x flag is enabled.

AFAIK, only ssed supports PCREs with the -R option.

So you'd need:

ssed -R 's/ \d {3}/.../gx'
ssed -R 's/(?x) \d {3}/.../g'

Or (ast-open sed, which also is the sed builtin of ksh93 if enabled):

ast-sed    's/\(?x\) \d \{3\}/.../g'
ast-sed -E 's/(?x) \d {3}/.../g'
ast-sed -A 's/(?x) \d {3}/.../g'

(for the 3 flavours of regexp it supports: basic, extended, augmented).

When the x flag is enabled, to match a literal space character, you need [ ] or prefix the space with \ (or use \x20 on ASCII based systems).

2
  • I thought /s is used to represent space. – tannoy connect Jan 25 at 23:26
  • @tannoyconnect \s (not /s) is the nonstandard equivalent of [[:space:]] which matches on any character classified as whitespace like tab, or space. That's even more characters than [[:blank:]]/\h in that it also includes vertical whitespace like cr, lf, vt, ff. – Stéphane Chazelas Jan 26 at 6:31

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.