Checking if char is within set - bash

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

Related

Checking if an integer is an element in array

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

[[Bash]] Search for combined Expressions in every row

I am very new to Bash Scripting and I have a question regarding my CheckOurCodingRules.sh script:
I want to search for every 'hPar,' in a textfile and if found it should be checked if there is a also a 'const' in the same row.
Thats what I got so far but there is something wrong here:
while read line
do
if [[ $line == *hPar\,* ]] && [[ $line == *const\*]];then
DOCUMENTATION_TEST_A=1
else
echo DOCUMENTATION_TEST_A=0
fi
done < $INPUT_FILE
if [[DOCUMENTATION_TEST_A=0]];then
echo "error: Rule1: No const before hpar"
fi
There are a couple of issues with your script, see the code below which works for me:
DOCUMENTATION_TEST_A=0 # initial value
while read line
do
# spaces between conditional and brackets, no backslashes
if [[ $line == *hPar,* ]] && [[ $line == *const* ]]
then
DOCUMENTATION_TEST_A=1
break # optional, no need to scan the rest of the file
fi
done < $INPUT_FILE
# spaces and $, -eq is used for numerical comparisons
if [[ $DOCUMENTATION_TEST_A -eq 0 ]];
then
echo "error: Rule1: No const before hpar"
fi
A cleaner solution would be to use grep:
if ! grep "hPar," $INPUT_FILE | grep "const" >/dev/null
then
echo "error: Rule1: No const before hpar"
fi

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

A simple bash program that prints the third character of a string, that uses [[ ]] (compare to method)

Unfortunately i tried this and it doesn't work, i must use the [[ ]]
read input
for i in input
do
if [[ i = "$input" ]]
then
echo "i"
fi
done
when I run this nothing happens, it only reads my input
This line:
if [[ i = "$input" ]]
should be:
if [[ "$i" = "$input" ]]
OR:
if [[ "$i" == "$input" ]]
PS: Same thing for input also.
Remember that variables in shell are accessed with $ prefix.
May be you can re-factor your script to this:
read input
for i in $input
do
[[ "$i" == "something" ]] && echo "$i"
done
I think when you use only numbers you can also try:
for i in input
do
if [[ $i -eq "$input" ]]
then
echo "$i"
fi
done

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