Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top
echo "223255/12345678                    " | grep '[0-9a-zA-Z/\-\?:\(\)\.,"\+]{1,34}'

According to the regex, it can have any of 0-9 a-z A-Z / - ? : ( ) . , " + of upto 34 chars in any order. Am I right?

In that case, why is it not printing the echoed value?

share|improve this question
up vote 1 down vote accepted

Try using egrep or pass the -E flag to grep:

echo "223255/12345678                    " | egrep '[0-9a-zA-Z/\-\?:\(\)\.,"\+]{1,34}'


echo "223255/12345678                    " | grep -E '[0-9a-zA-Z/\-\?:\(\)\.,"\+]{1,34}'
share|improve this answer
That would still match on x@, \\ , possibly é and not - – Stéphane Chazelas Mar 26 '13 at 21:17

There are several problems with your code:

  • Inside [...], the only special characters are - and ] (though there's also [: which introduces character classes) and the way to escape them is not with \, but for - by making it the first or last character in the list ([-...] or [...-]) and for ] by making it the first ([]...]). Above, \-\ means any character in the range \ to \, that is it includes \, but not -. So you'd need [-0-9a-zA-Z/?:().,"+].
  • Beware that ranges like a-z and A-Z are locale-dependant (like may include things like é, ŝ...) and may also include multibyte characters. If you only want to include ASCII characters in those ranges, you should fix the locale to C: ... | LC_ALL=C grep ...
  • {x,y} is an extended regular expression operator (as supported by grep -E). The corresponding basic regular expression (as supported by grep) operator is \{x,y\}. So LC_ALL=C grep '[-0-9a-zA-Z/?:().,"+]\{1,34\}'
  • in grep pattern, grep checks if pattern matches anywhere inside each line of input. If you want it to match the whole line, you need the -x option (for exact) or anchor the pattern at the start and end with the ^ and $ regexp operators. grep -E 'x{1,34}' is the same as grep x, because a line that contains any sequence of 1 to 34 x also contains one x and a line that contains an x contains a sequence of 1 x so matches the x{1,34} regexp.
  • Assuming you're doing echo "$var" | grep the-pattern, beware that it's not reliable, because some echo for instance would turn -neen into an empty string while others would turn \n into a newline character for instance. Also note that grep matches on every line of the input, not on the whole input, so your check might not be valid if $var may contain newline characters. Best would be to use expr instead or the [[ $var =~ pattern ]] operator of ksh93, zsh or bash.

To sum up, if you want to check that $var is made of 1 to 34 of those ASCII characters, you should write it:

if LC_ALL=C expr "x$var" : 'x[-0-9a-zA-Z/?:().,"+]\{1,34\}$' > /dev/null; then
  echo yes
  echo no

(expr anchors the pattern to the start implicitly as if there was a ^ regexp operator)

share|improve this answer
This was perhaps a bit more than the OP meant to ask for, but it's a great reference! I'm keeping this for when I'm hitting my head against the desk with some weird regex problem I just can't figure out. (It's a shame one cannot favorite answers.) – Michael Kjörling Mar 26 '13 at 21:36
Thank you for taking time in suggesting solutions for problems in my regex. – would_like_to_be_anon Apr 3 '13 at 18:10

maybe escape the / character.....what is the (\) used for? But Seems like since you are within single quotes you don't have to escape everything you put in there.

My suggestion to debug is to remove some of the characters and see what is wrong with your pattern.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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