Does this check for spaces? If so, how can I avoid it?
[^[:digit:]] ]]
I’m trying to check for non-digits, but I want to skip checking for spaces.
My understanding is that the space between the ]] ]] is a check for space, but when I remove that space, the program throws errors, expecting a binary operator.
I do think of it as part of one logical component; the first condition of the if statement, before the ||.
I don’t fully understand regex, so to the best of my knowledge, [^[:digit:]] ]] says, NOT a digit, meaning not 0-9. That last ]] is for closing the if.
But a space is a non-digit, so maybe I should be using ^[0-9]? From what I’ve read, there are subtle differences between [^[:digit:]] ]] and ^[0-9], and I don’t fully understand them.
I’ve tried removing some sets of brackets, but it didn’t help.
Which brackets would you remove and how would that change the meaning of the expression? Why/how would that change the behavior? Deleting things randomly isn’t a good way to accomplish anything.
What is the meaning of ${string:$i:1}? What exactly are you checking/testing?
Can you explain in English what you’re trying to accomplish and the steps to get there?
if runs a command and optionally branches based on the command’s exit status. The command evaluated here is [[ ${string:$i:1} =~ [^[:digit:]] ]].
[[ ${string:$i:1} =~ [^[:digit:]] ]] evaluates an expression. The expression it tests is ${string:$i:1} =~ [^[:digit:]]. Note, the closing ]] matches the opening [[ and is not part of the “test”.
The [[ expression ${string:$i:1} =~ [^[:digit:]] does a regex match (=~) using the value ${string:$i:1} and the regex [^[:digit:]].
The regex [^[:digit:]] matches any chars that are not digits.
There is no [^[:digit:]] ]] atom in this code in any logical way.
If any of these parts were not already apparent to you, you should slow down and understand the code before trying to modify it. Trying to modify the behavior of code without first understanding the basic structure of code isn’t programming; it’s brute force randomness.
There is no [^[:digit:]] ]] atom in this code in any logical way.
By atom, I think you mean a single element? That comes from the user input which contains a space, just as a test:
echo "Please enter a number/string: "
read -r string #45393195 03436467 - test string/input
set -x
for (( i=0; i <= ${#string}-1; i++ ))
do
if [[ ${string:$i:1} =~ [^[:digit:]] ]] || [[ ${#string} -le 1 ]]
then
echo "Input can only contain digits, and more than 1 character. Try again: "
main
fi
done
Am I wrong to say that a space is also a non-digit, that would be caught by [^[:digit:]] ? I’m not sure how I could alter it to avoid spaces. That’s why I mentioned trying ^[0-9], as I see it being more explicit (only numbers, no special chars, or spaces), although I would want to catch special chars.
I’m saying the regex is [^[:digit:]] and the trailing ]] in [^[:digit:]] ]] is not part of the regex, The regex has exactly two [ and two ]. You can’t drop any of them. There is no space in the regex. As such, the following doesn’t make much sense:
Why would you test a regex against individual characters? The whole point of regexes is for string matching?
A space is a non-digit. [^[:digit]] would match a string.
» string='45393195 03436467'
» for (( i=0; i <= ${#string}-1; i++ )); do
[[ ${string:$i:1} =~ [^[:digit:]] ]] && echo "String contains a non-digit, [${string:$i:1}]"
done
===>
String contains a non-digit, [ ]