What is a regular expression for a positive integer? I need it in an if
clause in a bash
script and I tried [[ $myvar == [1-9][0-9]* ]]
and I don't get why it says, for instance, that 6 is not an integer and 20O0O0
is.

- 4,695
- 4
- 28
- 39

- 55
- 1
- 5
-
"Positive integer" isn't specific enough. A leading zero might be legal, especially if the literal is specified in base-8. Is a leading `+` legal? Finally, `==` doesn't perform regular expression matching; it performs *pattern* matching. – chepner Dec 17 '16 at 15:39
-
^[1-9][0-9]*$ doesnt work :/ – adikinzor Dec 17 '16 at 15:41
-
leading 0 is not legal – adikinzor Dec 17 '16 at 15:42
3 Answers
The ==
operator performs pattern matching, not regular expression matching. [1-9][0-9]*
matches a string that starts with 1-9, following by a digit in the range 0-9, followed by anything, including an empty string. *
is not an operator, but a wildcard. As such, basic pattern matching is not sufficient.
You can use extended pattern matching, which can be enabled explicitly, or (in the case of newer versions of bash
) is assumed to be enabled for the argument to ==
and !=
.
shopt -s extglob # may not be necessary
if [[ $myvar == [1-9]*([0-9]) ]]; then
The pattern *([0-9])
will match zero or more occurrences of the pattern enclosed in parentheses.
If you want to use a regular expression instead, use the =~
operator. Note that you now need to anchor your regular expression to the beginning and end of the string you are matching; patterns do so automatically.
if [[ $myvar =~ ^[0-9][1-9]*$ ]]; then
Note that some of the confusion stems from the fact that [...]
is both a legal regular expression and pattern, and that characters like *
are used in both but with slightly different meanings. Also note that extended patterns are equivalent in power to regular expressions (anything you can match with one you can match with the other), but I leave the proof of that as an exercise to the reader.

- 497,756
- 71
- 530
- 681
-
`if [[ $myvar == [1-9]+([0-9]) ]]; then` seems to not work for `[1,9]` but `if [[ $myvar == [1-9]*([0-9]) ]]; then` i think does the thing. thanks – adikinzor Dec 17 '16 at 16:05
-
Ah, sorry about that. If you allowed the number to start with 0, you could simply use `+([0-9])`, and I think I had that in mind when I wrote the answer. In your case, you do want to use `*` instead. – chepner Dec 17 '16 at 18:03
[[ $myvar =~ ^[+]*[[:digit:]]*$ ]] && echo "Positive Integer"
shouldn't do it?
If a 0
is not a positive number in your description and you are not ready to accept leading zeros or plus, then do
[[ $myvar =~ ^[1-9]+[[:digit:]]*$ ]] && echo "Positive Integer"

- 21,411
- 5
- 55
- 102
-
No. Firstly it prints Pos integer when the variable is 0 and also accepts variables that begin with 0... – adikinzor Dec 17 '16 at 15:58
-
-
There is no need to use regex to check a positive integer. Just (( ... ))
construct like this:
isInt() {
# do sanity check for argument if needed
local n="$1"
[[ $n == [1-9]* && $n -gt 0 ]] 2>/dev/null && echo '+ve integer' || echo 'nope'
}
Then use it as:
isInt '-123'
nope
isInt 'abc'
nope
isInt '.123'
nope
isInt '0'
nope
isInt '789'
+ve integer
isInt '0123'
nope
foo=1234
isInt 'foo'
nope

- 761,203
- 64
- 569
- 643
-
-
-
-
@chepner: There is no assumption. Passed argument is either a positive integer or not. – anubhava Dec 17 '16 at 15:52
-
If you pass `foo` as the argument, and there is a global variable named `foo` with an integer value greater than 0, `isInt foo` is going to return true. `foo` is not a positive integer, though its *value* is. That might be OK, but it is at odds with the question as stated; the *string* `foo` is certainly not a positive integer. – chepner Dec 17 '16 at 15:55
-
-
@adikinzor: Leading zeroes are allowed in a positive integer. If you want to disallow that then use: `isInt() { [[ $1 != 0* ]] && (($1 > 0)) 2>/dev/null && echo '+ve integer' || echo 'nope'; }` – anubhava Dec 17 '16 at 15:59
-
-
This answer doesn't accept a `0`, or `005` which are (odd, yes) but valid integers. Also, it accepts `1+2`, `'5+a'` (if a is a valid integer **expression** like `a='2+2'`), `1*10**4`, and `16#11`, all which should be rejected IMO. Accept `5+00003` but reject `5+00008`.Maybe this approach should be re-evaluated. – Dec 17 '16 at 23:41
-