I currently have code as
if [[ "$FIRSTFLAG" == 1 ]] ; then
all_comp+=("FIRST")
fi
if [[ "$SECONDFLAG" == 1 ]] ; then
all_comp+=("SECOND")
fi
if [[ "$THIRDFLAG" == 1 ]] ; then
all_comp+=("THIRD")
fi
all_comp is just an array
So, im working on a solution to reduce the repetitive code
I know that we can use case here.
I wonder if there is a solution that can be done using array and for loop \
For example(I know its syntactically wrong)
names=("FIRST" "SECOND" "THIRD")
for i in $names[#]; do
if [[ ${i}FLAG == 1 ]]; then <- This line is the issue
all_comp+=("$i")
fi
done
So please tell me if there is a solution for such code example
You need to use indirect expansion by saving the constructed variable name, e.g. iflag=${i}FLAG, then you can use access the indirect expansion with ${!iflag}, e.g.
FIRSTFLAG=1
SECONDFLAG=0
THIRDFLAG=1
all_comp=()
names=("FIRST" "SECOND" "THIRD")
for i in ${names[#]}; do
iflag=${i}FLAG
if [[ ${!iflag} == 1 ]]; then
all_comp+=("$i")
fi
done
echo ${all_comp[#]} # Outputs: FIRST THIRD
Oh another answer, you can make use of the arithmetic expansion operator (( )) i.e.
FIRSTFLAG=1
SECONDFLAG=0
THIRDFLAG=1
all_comp=()
names=("FIRST" "SECOND" "THIRD")
for i in ${names[#]}; do
if (( ${i}FLAG == 1 )); then
all_comp+=("$i")
(( ${i}FLAG = 99 ))
fi
done
echo ${all_comp[#]} # FIRST THIRD
echo $FIRSTFLAG # 99
echo $SECONDFLAG # 0
echo $THIRDFLAG # 99
Reference:
https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#Shell-Parameter-Expansion
Related
Because bash returns me that != is invalid, but it's a basic operator.
I try to use it in a three expression for loop
for (( c=1; ${!c}!=""; c++ ))
do
You can, but it's not really the usual way to check if there are empty arguments.
for((i=1; i<=$#; ++i)); do
[[ "${!i}" ]] || echo "$0: Argument $i is empty" >&2
done
If you don't care about the index, just looping over the actual arguments is even simpler.
for arg in "$#"; do
[[ "$arg" ]] || echo "$0: Empty argument" >&2
done
Notice how we print diagnostics to standard error, and take care to include the name of the script which generates the diagnostic in the message.
You very rarely need to check for empty arguments in practice, but perhaps this is a learning exercise.
You can't do string comparison in a (()) because it's only arithmetic.
What you could do is something like this, where the string check is separate test after incrementing the counter var:
c=0
while (( c += 1 )) && [[ -n ${!c} ]]; do
echo "$c ${!c}"
done
When I execute below script it works fine:
if [[ "[1,2,3]" =~ .*1.* ]]; then
techStatus=1
else
techStatus=0;
fi
echo $techStatus
Output is 1
But when we changes it to variable it does not work.
var1=[1,2,3]
var2=1
if [[ "$var1" =~ .*"$var2".* ]]; then
techStatus=1
else
techStatus=0;
fi
echo $techStatus
Output is 0.
Please help me figure out what is wrong here.
A better & readable approach would be to convert var1 to array and loop through var1.
var1=(1 2 3)
var2=1
for elem in "${var1[#]}"; do
if [[ "$elem" -eq "$var2" ]]; then
techStatus=1
break
else
techStatus=0
fi
done
echo "$techStatus"
I am trying to figure out a sane way to do a NOT clause in a case. The reason I am doing this is for
transcoding when a case is met, aka if I hit an avi, there's no reason to turn it into an avi again, I can
just move it out of the way (which is what the range at the base of my case should do). Anyway, I have some
proto code that I wrote out that kind of gives the gist of what I am trying to do.
#!/bin/bash
for i in $(seq 1 3); do
echo "trying: $i"
case $i in
! 1) echo "1" ;; # echo 1 if we aren't 1
! 2) echo "2" ;; # echo 2 if we aren't 2
! 3) echo "3" ;; # echo 3 if we aren't 3
[1-3]*) echo "! $i" ;; # echo 1-3 if we are 1-3
esac
echo -e "\n"
done
expected results would be something like this
2 3 ! 1
1 3 ! 2
1 2 ! 3
Help is appreciated, thanks.
This is contrary to the design of case, which executes only the first match. If you want to execute on multiple matches (and in your design, something which is 3 would want to execute on both 1 and 2), then case is the wrong construct. Use multiple if blocks.
[[ $i = 1 ]] || echo "1"
[[ $i = 2 ]] || echo "2"
[[ $i = 3 ]] || echo "3"
[[ $i = [1-3]* ]] && echo "! $i"
Because case only executes the first match, it only makes sense to have a single "did-not-match" handler; this is what the *) fallthrough is for.
You can do this with the extglob extension.
$ shopt -s extglob
$ case foo in !(bar)) echo hi;; esac
hi
$ case foo in !(foo)) echo hi;; esac
$
I'm writing a VERY simple bash script with an "IF" statment. I've written many before, but for some reason it will not read the "${hitA1} == 0" argument. ${hitA1} is read from a file, and it is actually reading it, and it does actually equal 0. Instead it goes to the second argument of "${hitA1} != 0". Any ideas?
Code:
CorHitA1=0
MissA1=0
for i in 44 50 53 58 71
do
late=`expr $i + 1`
hitA1=`sed -n ${i}p _TMP_Acc1.txt`
hitlateA1=`sed -n ${late}p _TMP_Acc1.txt`
if [[ ${hitA1} == 0 ]]; then
echo "HEY!!!!!"
CorHitA1=`expr ${CorHitA1} + 1`
elif [[ ${hitA1} != 0 ]]; then
echo "Nope..."
echo ${hitA1}
fi
echo "CorHitA1 = " ${CorHitA1}
done
With bash, you should use (( for arithmetic tests:
if ((hitA1 == 0)); then ...
(With arithmetic evaluation, you don't need the $ nor do you need to quote the variable.)
Or you can use the -eq operator with [[:
if [[ $hitA1 -eq 0 ]]; then ...
If you don't do one of the above, and the line in the file you're extracting has whitespace in it, then [[ $hitA1 == 0 ]] will return false because == is string equality, and a string with whitespace is not the same as a string without.
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