Checking if an integer is an element in array - bash

I need to check if the value c exists in an integer array, I'm aware of how to approach this using for loops and if statements:
for c in {1..100};do
sequence=(2 4 6 8 10 12 14 16)
for value in "${sequence[#]}";do
if [[ $value -eq $c ]];then #If c exists in sequence
flag=1
break
fi
done
done
But I don't want this, I tried something similar to this:
[[ ${sequence[*]} =~ $c ]]
But it didn't give me the desired results, I think it works only with string arrays, not integers.
How could I approach this?

Converting my comment to answer so that solution is easy to find for future visitors.
You may use this grep + printf solution:
grep -qFx "$c" <(printf '%s\n' "${sequence[#]}") && echo "found" || echo "nope"

The problem with this method [[ ${sequence[*]} =~ $c ]] is that if $c is 1, than it'll match all instances with 1. Try this approach, make your sequence a regex like this
re=${sequence[*]}
re=${re// /|}
$ echo $re
2|4|6|8|10|12|14|16
Testing
c=1
$ [[ $c =~ $re ]] && echo ok || echo fail
fail
c=11
$ [[ $c =~ $re ]] && echo ok || echo fail
fail
c=12
$ [[ $c =~ $re ]] && echo ok || echo fail
ok

Related

Shell Script - Case statement which finds exactly numbers (without +,-,/,*)

Briefly,
I have a variable ($num) which contains random number(max.18), I need a case statement in shell (because along with checking number, I also have some alphabet conditions) which should validate the user input with the variable (must be less than $num).
Ex:
case $input in
...
1) ... ;;
2) ... ;;
...
so, here if I have only two conditions than I can write code like this, but my variable $num contains random number, how can I write case conditions which satisfies my below requirements.
If user inputs numbers like (1/3,3*1,3-2,2+1) it should not validate as a number
If user inputs numbers like (0001 or 01 or 000001) it should not validate as a number
The case condition should execute only if user inputs number between 1-$num no other number formats or symbols should not allowed.
Ex:
case $input in
[nN*]) ...
[aA*]) ...
...
*) if echo "$input" | egrep '^\-?[0-9]+$'; then
typeset -LZ num
num="$input"
if [ "$input" != "$num" ]; then
echo "$input not a valid number"
fi
else
echo "please choose proper choice option"
fi
;;
This code works but I want a normal case condition which should satisfy my requirements like if we have two or three options we can simply write the code but what if we have random options (which may decrease or increase) how to write a case condition in that case.
Thanks!
If the usage of a case is not compulsory, try and use some regex validation to have more control on what is allowed and what not:
[[ $input =~ ^[1-9][0-9]*$ ]]
# ^ ^ ^ ^
# beginning | | end
# | any digit
# a digit from 1 to 9
This checks that the data in $input contains a number that does not start with 0.
$ r=001
$ [[ $r =~ ^[1-9][0-9]*$ ]] && echo "yes"
$
$ r=1
$ [[ $r =~ ^[1-9][0-9]*$ ]] && echo "yes"
yes
$ r="3+1"
$ [[ $r =~ ^[1-9][0-9]*$ ]] && echo "yes"
$
You can then check if the number is lower than the stored one:
[ $r -le $num ]
All together:
$ num=15
$ r=5
$ [[ $r =~ ^[1-9][0-9]*$ ]] && [ $r -le $num ] && echo "yes"
yes
$ r=19
$ [[ $r =~ ^[1-9][0-9]*$ ]] && [ $r -le $num ] && echo "yes"
$
$ r="3+1"
$ [[ $r =~ ^[1-9][0-9]*$ ]] && [ $r -le $num ] && echo "yes"
$
read -p "enter number" yournumber
re='^[0-9]+$'
if ! [[ $yournumber =~ $re ]] ; then
echo "error: Not a number" >&2; exit 1
fi
This is only code rest of the things you need to do it.

Bash Shell Script Variable Value Check for integer and number range

im trying to do a Number Check not including decimals as well as within range check but it is not working
example of accepted numbers: 1, 10, 100
not accepted numbers: 1.1, 10.1, 100.1
echo "Qty Sold: "
read sold
if [[ "$sold" =~ `^([0-9])$` && "$sold" -gt 0 && "$sold" -lt 999 ]] ;
then
echo "ok"
else
echo "Error, Qty Sold Must be Positive Integer";
fi
Remove the backticks which exists around your regex and use + after [0-9] to match one or more digits.
if [[ "$sold" =~ ^[0-9]+$ && "$sold" -gt 0 && "$sold" -lt 999 ]] ;
Example:
$ sold=12
$ if [[ "$sold" =~ ^[0-9]+$ && "$sold" -gt 0 && "$sold" -lt 999 ]] ; then echo 'Ok'; else echo 'NOT ok'; fi
Ok
$ sold=0
$ if [[ "$sold" =~ ^[0-9]+$ && "$sold" -gt 0 && "$sold" -lt 999 ]] ; then echo 'Ok'; else echo 'NOT ok'; fi
NOT ok
$ sold=1000
$ if [[ "$sold" =~ ^[0-9]+$ && "$sold" -gt 0 && "$sold" -lt 999 ]] ; then echo 'Ok'; else echo 'NOT ok'; fi
NOT ok
Without using regex:
((sold>0 && sold <999)) 2>/dev/null && echo "ok" || echo "Error, Qty Sold Must be Positive Integer"
The [[ syntax is a bit different from [ syntax. You do not need any delimiter around the regex in =~. So no / or backtick or apostrophe or ampersand is needed (only if regex contains a space. It can be escaped by backslash or add apostrophe or ampersand around the space or use [[:space:]] instead (which also includes TAB and some other whitespace characters)). What is more the ampersand also not needed around $sold (only in [[!). So the conditional part may be like this
if [[ $sold =~ ^[[:digit:]]{1,3}$ && $sold -gt 0 && $sold -lt 999 ]]; then echo ok
else echo "Error, Qty Sold Must be Positive Integer between 1 and 998";
fi
This checks if one, two or three digits are entered and it is not zero.

Bash if variable is an integer

I'm trying to write an if statement in bash that will exit if the variable supplied is not an integer. I will eventually be nesting this if statement within a while loop.
When I do run this I am getting an syntax error.
#!/bin/bash
if [ $f1 != ^[0-9]+$ ]
then
exit 1
fi
I have always like the integer test using the equality test construct:
[ $var -eq $var 2>/dev/null ] || exit 1
If var is not an integer, the equality fails due to the error generated. It is also POSIX compliant as it doesn't rely on character classes or the bash [[ construct.
You better negate the condition like this:
if [[ ! "$f1" =~ ^[0-9]+$ ]]; then
exit 1
fi
note the [[ and ]] syntax for the regular expressions, together with ! to negate it. Then, we use =~ for regexs.
Test
$ r=23a
$ [[ ! "$r" =~ ^[0-9]+$ ]] && echo "no digit" || echo "digit"
no digit
$ r=23
$ [[ ! "$r" =~ ^[0-9]+$ ]] && echo "no digit" || echo "digit"
digit

Checking if char is within set

I'm trying to check if some string from length 1 and has only following chars: [RGWBO].
I'm trying the following but it doesn't work, what am I missing?
if [[ !(${line[4]} =~ [RGWBO]) ]];
This is what you want:
if [[ ${line[4]} =~ ^[RGWBO]+$ ]];
This means that the string right from the start till the end must have [RGWBO] characters one or more times.
If you want to negate the expression just use ! in front of [[ ]]:
if ! [[ ${line[4]} =~ ^[RGWBO]+$ ]];
Or
if [[ ! ${line[4]} =~ ^[RGWBO]+$ ]];
This one would work with any usable version of Bash:
[[ -n ${LINE[0]} && ${LINE[0]} != *[^RGWB0]* ]]
Even though I prefer the simplicity of extended globs:
shopt -s extglob
[[ ${LINE[0]} == +([RGWBO]) ]]
Use expr (expression evaluator) to do substring matching.
#!/bin/bash
pattern='[R|G|W|B|O]'
string=line[4]
res=`expr match "$string" $pattern`
if [ "${res}" -eq "1" ]; then
echo 'match'
else
echo 'doesnt match'
fi
Approach
Test the string length with ${#myString}, if it's egal to 1 proceed to step 2 ;
Does is contains your pattern.
Code
re='[RGWBO]';
while read -r line; do
if (( ${#line} == 1 )) && [[ $line == $re ]]; then
echo "yes: $line"
else
echo "no: $line"
fi
done < test.txt
Resources
You may want to look at the following links:
Bash: Split string into character array's answer ;
Length of a string, use ${#myString} ;
Extracting parts of strings, use ${myString:0:8} ;
Data
The test.txt file contains this
RGWBO
RGWB
RGW
RG
R
G
W
B
O
V

Repetitive Sequence in Bash

I'm stuck in something in my bash script, I have a string that composes of a repetitive sequence of 20s, e.g. 202020, there might be more or less 20s, e.g. 2020 or 2020202020, I want to create an if condition that if finds any strange number inside, e.g. 30 in 20203020, gives an error.
Any ideas?
this should do the test:
[[ "$var" =~ "^(20)+$" ]]
check this:
kent$ [[ "202" =~ "^(20)+$" ]] && echo "y" || echo "n"
n
kent$ [[ "20203" =~ "^(20)+$" ]] && echo "y" || echo "n"
n
kent$ [[ "20202002" =~ "^(20)+$" ]] && echo "y" || echo "n"
n
kent$ [[ "20202020" =~ "^(20)+$" ]] && echo "y" || echo "n"
y
how about this example, can you use it?
if [ "`echo "202020302020" | sed -e 's/20//g'`" ];
then echo "there is something";
fi
Extended patterns are a tiny bit more compact than regular expressions.
shopt -s extglob
if [[ $str = +(20) ]]; then
echo "twenties"
else
echo "mismatch"
fi
At some point, bash changed to treat all patterns in [[...]] expressions as extended patterns, so the shopt command may not be necessary.

Resources