I'm going to learn bash programming. I just wrote a simple script in order to read numbers from input stream and check them to be in valid numerical format using regular expression.
in fact script should take input until the input be nonnumerical.
but it doesn't work properly.
code:
i=0
echo "plz enter number in valid format: "
while true
do
read input
if [[ $input =~ *[^0-9]* ]]; then
echo "YOU DIDN'T ENTER A VALID NUMBER"
break
else
arr[$i]=$input
echo $input >> inputnums
fi
done
when i enter a number or character condition is true. I mean i have echo "message" in output.
You're mixing shell globing with regex, change your if condition to:
if [[ $input =~ [^0-9] ]]; then
regex should use .* not * as used by shell shell glob.
Remove the * from the regex:
#!/bin/bash
i=0
echo "plz enter number in valid format: "
while true
do
read input
if [[ $input =~ ^[^0-9]+$ ]]; then
echo "YOU DIDN'T ENTER A VALID NUMBER"
break
else
arr[$i]=$input
echo $input
fi
done
Related
Made a script that the user gives a "parameter" and it prints out if it is a file, directory or non of them. This is it :
#!/bin/bash
read parametros
for filename in *
do
if [ -f "$parametros" ];
then
echo "$parametros is a file"
elif [ -d "$parametros" ];
then
echo "$parametros is a directory"
else
echo " There is not such file or directory"
fi
exit
done
Altough i want the user to be allowed to give only one word as a parameter. How do i make this happen ? (For example if user press space after first word there would be an error message showing "wrong input")
#!/bin/bash
read parametros
if [[ "$parametros" = *[[:space:]]* ]]
then
echo "wrong input"
elif [[ -f "$parametros" ]]
then
echo "$parametros is a file"
elif [[ -d "$parametros" ]]
then
echo "$parametros is a directory"
else
echo " There is not such file or directory"
fi
See http://mywiki.wooledge.org/BashFAQ/031 for the difference between [...] and [[...]].
You have to use the $#. It gives the number of the parameters.
The code will be something like:
if [ "$#" -ne 1 ]; then
printf 'ERROR!\n'
exit 1
fi
First, I'm curious why you want to restrict to one word - a file or directory could have spaces in it, but maybe you are preventing that somehow in your context.
Here are a few ways you could approach it:
Validate the input after they enter it - check if it has any spaces, eg: if [[ "parametros" == *" " ]]; then...
Get one character at a time in a while loop, eg with: read -n1 char
Show an error if it's a space
Break the loop if it's 'enter'
Build up the overall string from the entered characters
1 is obviously much simpler, but maybe 2 is worth the effort for the instant feedback that you are hoping for?
This question already has an answer here:
Weird behavior of BASH glob/regex ranges
(1 answer)
Closed 4 years ago.
I'm writing a script to check a password if it has upper case or not, but it always shows that it has upper case.
I tried to use
if [[ $password =~ [A-Z] ]]; then
echo "Contains Upper Case"
but it always prints that.
This is my script:
read -p "Enter Password: " password
if [ ${#password} -lt 8 ]; then
echo "TOO SHORT , MAN! "
fi
if [[ $password =~ [A-Z] ]]; then
echo "Contains Upper Case"
fi
Do not use [A-Z]. It works only in some language settings / locales (the ones where ordering looks like ABCD...Zabcd...z, intead of like AaBb...Zz).
For your code to work everywhere, use [[:upper:]] instead.
#!/usr/bin/env bash
[ -n "$BASH_VERSION" ] || { echo "ERROR: Shell is not bash" >&2; exit 1; }
if [[ $password =~ [[:upper:]] ]]; then
echo "Contains at least one upper-case character"
else
echo "Does not contain one or more upper-case characters"
fi
Say you have the user enter in a number 0-3 and want to test it. The most common way seems to be:
[[ $var =~ ^[0-3]$ ]]
But how would you use this with:
test expression
My initial attempt doesn't evaluate correctly, e.g.
read -p "Enter selection [0-3] > "
if test $REPLY == '^[0-3]$' ; then
...
It just evaluates the if statement as false.
test is equivalent to the [ ] structure, but not to [[ ]], which is an extended version. The regex =~ is only available in the extended test, so for simple test or [ ] you have to pull the regex evaluation from elsewhere.
One fix is grep. This pipeline will catch and print the matches:
echo "$REPLY" | grep '^[0-3]$'
Using test with a string evaluates positively if the string is non-empty. Compare these two:
test "" && echo ok
and
test "a" && echo ok
Knowing this, it's now easy to build a compound test from the both elements.
test "$(echo "$REPLY" | grep '^[0-3]$')"
And this can be applied to the script:
read -p "Enter selection [0-3] > "
if test "$(echo "$REPLY" | grep '^[0-3]$')"; then
...
fi
You can use a regex in Bash like this:
echo -n "Your answer> "
read REPLY
if [[ $REPLY =~ ^[0-9]+$ ]]; then
echo Numeric
else
echo Non-numeric
fi
Please check the post Using Bash's regular expressions.
In unix, i need to read a o/p which should be numeric, if suppose user entered character it should throw error as "invalid identifier". Is that possible in if loop?
try this...
unset get_num
while [[ ! ${get_num} =~ ^[0-9]+$ ]]; do
echo "Please enter in a number:"
read get_num
done
echo This is a number : ${get_num}
I have a Bash statement to get user input(a single character) into tmpchar :
read -n 1 -t 1 tmpchar
and I can check for printable character input like this:
if [ "$tmpchar" = "n" ] || [ "$tmpchar" = "N" ]; then
# do something...
fi
Now my question is: If user input just a Return, or ESC, or Ctrl+a, Ctrl+b etc, how do I check for them?
ENV: openSUSE 12.3 , Bash 4.2.42(1)-release
Maybe you're looking for ANSI-C quoting. E.g., Ctrl-a is represented as $'\ca'.
Use the regex match operator =~ inside of [[ ... ]]:
if [[ $tmpchar =~ [[:cntrl:]] ]]; then
# It's a control character
else
# It's not a control character
fi
Note that read -n1 won't do what you expect for a variety of special characters. At a minimum, you should use:
IFS= read -r -n1
Even with that, you'll never see a newline character: if you type a newline, read will set the reply variable to an empty string.
If you want to know if a character isn't a member of the set of printable characters, use a complementary set expression. This seems to work fine with case:
for c in $'\x20' $'\x19'; do
case "$c" in
[[:print:]]) echo printable;;
[^[:print:]]) echo 'not printable';;
*) echo 'more than one character?';;
esac
done
(outputs printable and then non printable)
for c in $'\x20' $'\x19'; do
if [[ $c = [[:print:]] ]]; then
echo printable
fi
if [[ $c = [^[:print:]] ]]; then
echo not printable
fi
done
works as well. If you want to know what characters sets your system supports, look at man 7 regex on linux or man 7 re_format on OS X.
You can filter the input with tr:
read -n 1 -t 1 tmpchar
clean=$(tr -cd '[:print:]' <<< $tmpchar)
if [ -z "$clean"]; then
echo "No printable"
else
echo "$clean"
fi
I find a trick to check for a sole Return input.
if [ "$tmpchar" = "$(echo -e '')" ]; then
echo "You just pressed Return."
fi
In other word, the highly expected way by #ooga,
if [ "$tmpchar" = $'\x0a' ]; then
echo "You just pressed Return." # Oops!
fi
does not work for Return anyhow, hard to explain.