I am trying to perform this regex with sed, but seems like sed does not support? It says invalid character range

echo "$info" | sed -e 's/(?:\d[\s-.]*){12,19}/*/g'

Trying to match any digits range with 12 to 19 regardless of whitespaces,-, or . characters

sed: 1: "s/(?:\d[\s-.]*){12,19}/ ...": RE error: invalid character range

Seems like the issue is fixed when I moved the dash up in the character range to (?:\d[-\s.]*){12,19} but it does nothing afterwards... Does that mean this is not matching? But regexr test cases say otherwise


1234 1234 1234 1234
VISA 1234123412341234 EXP 1222 CVV 123

This part of the regexp is the source of the error: [\s-.]

If you want - to be treated as just another character in a bracket expression, then put it at the beginning or the end of the expression. Otherwise, it will be treated as a range.

For example:

  • [a-z] means "match all lowercase letters from a to z"
  • [-az] or [az-] mean "match a dash, an 'a', or a 'z'"

BTW, no version of sed that I know of understands the perl-ish \d as a synonym for [0-9] or [:digit:]. Some versions of sed (e.g. GNU sed) understand \s as a synonym for spaces and tabs ([:blank:]), but certainly not all. And those that do understand \s, probably only understand it outside of bracket expressions (i don't know of any that do understand it inside [] but that doesn't mean there isn't some obscure sed variant that does).

And, AFAIK, sed doesn't understand perl's (?:) to mean a non-capturing subexpression.

To use Extended Regular Expression (ERE) features like {} without escaping them as \{ and \}, you need to use sed's -E option (and escaping them might be a GNU extension, like it is for \+, so may not work for all versions of sed).

To match 12-19 digits that might contain spaces or dashes and replace them with asterisks, you first need to remove the spaces and dashes, and then try to match 12-19 digits. e.g.

echo "$info" | sed -E -e 's/[[:blank:]-]//; s/[[:digit:]]{12,19}/*/g'

NOTE: If you don't care about portability and are never likely to deal with ancient or proprietary versions of sed, this will be fine. Otherwise, stick to Basic Regular Expressions (BRE) or use perl -n or perl -p instead of sed (and definitely use perl if you want to use perl's dialect of regular expressions).

Also note that this will affect the entirety of whatever is in $info, so all spaces and dashes will be stripped. Depending on what's in $info, this may not be what you want.

If $info is likely to contain other text (e.g. VISA 1234123412341234 EXP 1222 CVV 123 instead of just 1234123412341234) then you should probably use awk or perl instead of sed so that you can easily work with each individual field rather than the entire line.

  • 1
    What do you mean by "use perl on a variable"? If you mean "Can I echo a variable into a perl script like I can with a sed script?" then yes, you can: e.g. echo "$info" | perl -p -e '.....'. You will probably find, though, that unless what you're doing is trivial, you will almost certainly be better off writing the entire script in perl rather than a shell script that calls awk, sed, and/or perl multiple times. – cas Jun 15 at 5:25
  • 1
    \{...\} are standard and were added to BREs before {..} were added to EREs (some EREs like in some awk / egrep implementations still don't support {...} as adding them breaks backward compatibility), – Stéphane Chazelas Jun 15 at 6:01
  • 1
    While GNU or ast-open sed supports \s outside of bracket expression, it doesn't support it inside. – Stéphane Chazelas Jun 15 at 6:03
  • 1
    @BaoThai the best way to get good with perl (or any language. or anything at all) is to practice it. starting with simple things and working your way up to more advanced stuff is exactly the right way to learn. – cas Jun 15 at 6:21
  • 1
    yeah, i know where \s came from. it used to mildly annoy me that other REs didn't have the perl niceties. eventually I stopped caring about it. some of them have since borrowed some features from perl and while that vaguely pleases me, i still don't care very much. – cas Jun 15 at 7:02

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.