The following code is displaying a Progress Bar on an HTML page. It runs fine but takes up far to many lines of code.
QUESTION:
- How would I go about transforming this into a for or while loop, replicating its functionality?
if [ $per_usage -ge 1 ] && [ $per_usage -le 10 ]
then
indg="|"
indb=""
indr=""
elif [ $per_usage -gt 10 ] && [ $per_usage -le 20 ]
then
indg="||"
indb=""
indr=""
elif [ $per_usage -gt 20 ] && [ $per_usage -le 30 ]
then
indg="|||"
indb=""
indr=""
elif [ $per_usage -gt 30 ] && [ $per_usage -le 40 ]
then
indg="||||"
indb=""
indr=""
elif [ $per_usage -gt 40 ] && [ $per_usage -le 50 ]
then
indg="|||||"
indb=""
indr=""
elif [ $per_usage -gt 50 ] && [ $per_usage -le 60 ]
then
indg="|||||"
indb="|"
indr=""
elif [ $per_usage -gt 60 ] && [ $per_usage -le 70 ]
then
indg="|||||"
indb="||"
indr=""
elif [ $per_usage -gt 70 ] && [ $per_usage -le 80 ]
then
indg="|||||"
indb="|||"
indr=""
elif [ $per_usage -gt 80 ] && [ $per_usage -le 90 ]
then
indg="|||||"
indb="||"
indr="||"
elif [ $per_usage -gt 90 ]
then
indg=""
indb=""
indr="||||||||||"
else
indg=""
indb=""
indr=""
fi
For example my output is like if per_usage value is 41
41 % |||||
Thank you in advance.
This sort of thing can be looped pretty easily:
#!/bin/bash
get_string () {
per_usage="$1"
if [ "$per_usage" -le 100 ] && [ "$per_usage" -ge 0 ]; then
echo -en "${per_usage}%\t"
bars=$(($per_usage / 10 + 1))
printf "%0.s|" $(seq 1 $bars)
echo
fi
}
i=0
while [ "$i" -le 100 ]; do
string=$(get_string "$i")
echo "$string"
let i++
done
In this example, the get_string function can be used to generate a string based on an input number. For instance, get_string 41 will print 41% |||||. In the little while loop below, the string for 0 - 100 is stored in the $string variable and printed.
bars stores the number of bars to print. Just one bar per 10%. Then printf and seq are used to print a | bars number of times.
Hopefully with this, you'll be on the right track to cleaning up your code.
Related
I am trying to test if a number is in the interval [1;100] here is what I did:
var=10
if [ $["$var" -gt "1" ] -a $["$var" -lt "100"] ] ; then
echo "yes"
else
echo "no"
fi
however when I run the script I get the error message:
./yourscript:line 2 10 -gt 1:error syntax in expression ,any ideas why?
delete unnecessaries and use &&:
var=10
if [ $var -gt 1 ] && [ $var -lt 100 ] ; then #or with -a if [ $var -gt 1 -a $var -lt 100 ] ;
echo "yes"
else
echo "no"
fi
I know how to do sequential for loops like:
for i in $(seq 0 63)
do
echo $i
done
This would print 0-63 .
But what if I wanted certain numbers looped like only 0, 5, 25, 43, 44, 51, 54.
I know I could do the following:
for i in $(seq 0 63)
do
if [ "$i" -eq 0 ] || [ "$i" -eq 5 ] || [ "$i" -eq 25 ] || [ "$i" -eq 43 ] || [ "$i" -eq 44 ] || [ "$i" -eq 51 ] || [ "$i" -eq 54 ]; then
echo $i
fi
done
But the result will be that it still goes through those loop iterations, and is not an efficient solution.
Is there something I can use with seq to describe these certain numbers 0,5,25,43,44,51,54?
If you want to iterate over a known list, you can simply store the elements, space-separated, in a variable and loop over that:
nums="0 5 25 43 44 51 54";
for i in $nums;
do echo $i;
done;
Is there any way to make the code run faster? i have tried everything!
Basically what i'm trying to do is:
to calculate all combinations of 52 variables, but only show the combinations where all numbers are only listed once! so there can't be fx: two 1's or three 49's
#!/bin/bash
#Enter here how many cards you use
howmanycards=52;
let run=$howmanycards+1;
i=1;
u=52;
totalrun=0;
SECONDS=0;
while [ $i -lt $run ]; do
let card$i=$u;
let i++;
let u--;
done
while [ -lt ]; do
let i=1;
if [ "$card1" -gt "52" ]; then let card2++;let card1=1; fi
if [ "$card2" -gt "52" ]; then let card3++;let card2=1; fi
if [ "$card3" -gt "52" ]; then let card4++;let card3=1; fi
if [ "$card4" -gt "52" ]; then let card5++;let card4=1; fi
if [ "$card5" -gt "52" ]; then let card6++;let card5=1; fi
if [ "$card6" -gt "52" ]; then let card7++;let card6=1; fi
if [ "$card7" -gt "52" ]; then let card8++;let card7=1; fi
if [ "$card8" -gt "52" ]; then let card9++;let card8=1; fi
if [ "$card9" -gt "52" ]; then let card10++;let card9=1; fi
if [ "$card10" -gt "52" ]; then let card11++;let card10=1; fi
if [ "$card11" -gt "52" ]; then let card12++;let card11=1; fi
if [ "$card12" -gt "52" ]; then let card13++;let card12=1; fi
if [ "$card13" -gt "52" ]; then let card14++;let card13=1; fi
if [ "$card14" -gt "52" ]; then let card15++;let card14=1; fi
if [ "$card15" -gt "52" ]; then let card16++;let card15=1; fi
if [ "$card16" -gt "52" ]; then let card17++;let card16=1; fi
if [ "$card17" -gt "52" ]; then let card18++;let card17=1; fi
if [ "$card18" -gt "52" ]; then let card19++;let card18=1; fi
if [ "$card19" -gt "52" ]; then let card20++;let card19=1; fi
if [ "$card20" -gt "52" ]; then let card21++;let card20=1; fi
if [ "$card21" -gt "52" ]; then let card22++;let card21=1; fi
if [ "$card22" -gt "52" ]; then let card23++;let card22=1; fi
if [ "$card23" -gt "52" ]; then let card24++;let card23=1; fi
if [ "$card24" -gt "52" ]; then let card25++;let card24=1; fi
if [ "$card25" -gt "52" ]; then let card26++;let card25=1; fi
if [ "$card26" -gt "52" ]; then let card27++;let card26=1; fi
if [ "$card27" -gt "52" ]; then let card28++;let card27=1; fi
if [ "$card28" -gt "52" ]; then let card29++;let card28=1; fi
if [ "$card30" -gt "52" ]; then let card31++;let card30=1; fi
if [ "$card31" -gt "52" ]; then let card32++;let card31=1; fi
if [ "$card32" -gt "52" ]; then let card33++;let card32=1; fi
if [ "$card33" -gt "52" ]; then let card34++;let card33=1; fi
if [ "$card34" -gt "52" ]; then let card35++;let card34=1; fi
if [ "$card35" -gt "52" ]; then let card36++;let card35=1; fi
if [ "$card36" -gt "52" ]; then let card37++;let card36=1; fi
if [ "$card37" -gt "52" ]; then let card38++;let card37=1; fi
if [ "$card38" -gt "52" ]; then let card39++;let card38=1; fi
if [ "$card39" -gt "52" ]; then let card40++;let card39=1; fi
if [ "$card40" -gt "52" ]; then let card41++;let card40=1; fi
if [ "$card41" -gt "52" ]; then let card42++;let card41=1; fi
if [ "$card42" -gt "52" ]; then let card43++;let card42=1; fi
if [ "$card43" -gt "52" ]; then let card44++;let card43=1; fi
if [ "$card44" -gt "52" ]; then let card45++;let card44=1; fi
if [ "$card45" -gt "52" ]; then let card46++;let card45=1; fi
if [ "$card46" -gt "52" ]; then let card47++;let card46=1; fi
if [ "$card47" -gt "52" ]; then let card48++;let card47=1; fi
if [ "$card48" -gt "52" ]; then let card49++;let card48=1; fi
if [ "$card49" -gt "52" ]; then let card50++;let card49=1; fi
if [ "$card50" -gt "52" ]; then let card51++;let card50=1; fi
if [ "$card51" -gt "52" ]; then let card52++;let card51=1; fi
while [ $i -lt $run ]; do
temp=${card}${i};
if [ "$temp" = "$card1" ] || [ "$temp" = "$card2" ] ||
[ "$temp" = "$card3" ] || [ "$temp" = "$card4" ] ||
[ "$temp" = "$card5" ] || [ "$temp" = "$card6" ] ||
[ "$temp" = "$card7" ] || [ "$temp" = "$card8" ] ||
[ "$temp" = "$card9" ] || [ "$temp" = "$card10" ] ||
[ "$temp" = "$card11" ] || [ "$temp" = "$card12" ] ||
[ "$temp" = "$card13" ] || [ "$temp" = "$card14" ] ||
[ "$temp" = "$card15" ] || [ "$temp" = "$card16" ] ||
[ "$temp" = "$card17" ] || [ "$temp" = "$card18" ] ||
[ "$temp" = "$card19" ] || [ "$temp" = "$card20" ] ||
[ "$temp" = "$card21" ] || [ "$temp" = "$card22" ] ||
[ "$temp" = "$card23" ] || [ "$temp" = "$card24" ] ||
[ "$temp" = "$card25" ] || [ "$temp" = "$card26" ] ||
[ "$temp" = "$card27" ] || [ "$temp" = "$card28" ] ||
[ "$temp" = "$card29" ] || [ "$temp" = "$card30" ] ||
[ "$temp" = "$card31" ] || [ "$temp" = "$card32" ] ||
[ "$temp" = "$card33" ] || [ "$temp" = "$card34" ] ||
[ "$temp" = "$card35" ] || [ "$temp" = "$card36" ] ||
[ "$temp" = "$card37" ] || [ "$temp" = "$card38" ] ||
[ "$temp" = "$card39" ] || [ "$temp" = "$card40" ] ||
[ "$temp" = "$card41" ] || [ "$temp" = "$card42" ] ||
[ "$temp" = "$card43" ] || [ "$temp" = "$card44" ] ||
[ "$temp" = "$card45" ] || [ "$temp" = "$card46" ] ||
[ "$temp" = "$card47" ] || [ "$temp" = "$card48" ] ||
[ "$temp" = "$card49" ] || [ "$temp" = "$card50" ] ||
[ "$temp" = "$card51" ] || [ "$temp" = "$card52" ]; then
let usefull++;
fi
let i++;
done
if [ $usefull -gt 51 ]; then
echo "[loops($totalrun)] $card52-$card51-$card50-$card49-$card48-$card47-$card46-$card45-$card44-$card43-$card42-$card41-$card40-$card39-$card38-$card37-$card36-$card35-$card34-$card33-$card32-$card31-$card30-$card29-$card28-$card27-$card26-$card25-$card24-$card23-$card22-$card21-$card20-$card19-$card18-$card17-$card16-$card15-$card14-$card13-$card12-$card11-$card10-$card9-$card8-$card7-$card6-$card5-$card4-$card3-$card2-$card1";
fi
let usefull=0;
if [ "$card52" -gt "52" ]; then
echo " ";
duration=$SECONDS
echo "$(($duration / 60)) min and $(($duration % 60)) sec";
exit;
fi
let card1++;
let totalrun++;
done
I have tried to create code priorities, but it dosen't seem to make a difference!
but what i have figured out is that the code that make the check, if there more than one number in it, is using a lot of performance! And i don't know what to do about that!
Thank you for your help.
Firstly, I think you need a workable implementation to get combinations in bash. Here is one that works with associative arrays. I implemented it to mimic this Java code:
#!/bin/bash
function combine() {
local index="$1"
local -a prefix=("${!2}")
local -a postfix=("${!3}")
local i=$index
while [ $i -lt ${#prefix[#]} ]; do
postfix+=(${prefix[#]:$i:1})
echo ${postfix[#]}
combine "$((i + 1))" prefix[#] postfix[#]
local postfix_last_char="$((${#postfix[#]} - 1))"
postfix=(${postfix[#]:0:$postfix_last_char})
((i++))
done
}
function get_combinations() {
local -a prefix_table=("${!1}")
local -a postfix_table=()
local index=0
combine 0 prefix_table[#] postfix_table[#]
}
function example_use() {
# Get all combinations of the numbers 0 to 9.
foo=({0..9})
get_combinations foo[#]
}
Now, one can begin to think about modifying the combine() function to impose an additional condition that we will only print out sets (arrays which contain only distinct elements.) So we can replace the line:
echo ${postfix[#]}
By a new call:
echo_if_is_a_set postfix[#]
Which is implemented as:
function echo_if_is_a_set() {
local -a input=("${!1}")
local -a entry_count_lookup
# Tally up the occurrences of each item.
for item in ${input[#]}; do
local current_count=${entry_count_lookup[$item]:-0}
((current_count++))
entry_count_lookup[$item]=$current_count
done
for value in ${!entry_count_lookup[#]}; do
if [ ${entry_count_lookup[$value]} -ne 1 ]; then
return
fi
done
echo ${input[#]}
}
Okay, but not quite done. We might still print the same combination twice, in the event that was passed in repeat elements. For example, if you did:
foo=(1 1 1)
get_combinations foo[#]
So, let's just call uniq, changing get_combinations to:
function get_combinations() {
local -a prefix_table=("${!1}")
local -a postfix_table=()
local index=0
combine 0 prefix_table[#] postfix_table[#] | sort | uniq
}
And, we're done. Running this with the input ({1..3}) prints:
1
1 2
1 2 3
1 3
2
2 3
3
But the nice thing about this implementation is that because it uses the associative arrays, we can actually be general, and input something like (2 Racecar 34), which would return:
2
2 34
2 Racecar
2 Racecar 34
34
Racecar
Racecar 34
Anyway, as a last comment, I'd say start with something like this and then you can optimize the algorithm for efficiency.
Also, Bash is probably not at all the right language for this. :-D
Can any one tell what wrong with this script ?. Because I am getting the error like
./timer: line 9: [13: command not found
./timer: line 12: [13: command not found
My script look like
#!/bin/bash
while :
do
HOUR=$(date +%H)
MINUTE=$(date +%M)
SECOND=$(date +%S)
if [$HOUR == 13] && [$MINUTE == 12] && [$SECOND == 1]
then ./binary
elif [$HOUR == 18] && [$MINUTE == 30] && [$SECOND == 1]
then ./binary
fi
done
put a space between the [ ... ]
Example:
if [$HOUR == 13] && [$MINUTE == 12] && [$SECOND == 1]
Should become
if [ $HOUR == 13 ] && [ $MINUTE == 12 ] && [ $SECOND == 1 ]
I think you must use "${VARIABLE}" and respect spaces for square brackets
This would give :
if [ "${HOUR}" == 13 ] && [ "${HOUR}" == 12 ] && [ "${HOUR}" == 1 ]
Hope that helps !
the test operators in bash need to have a space by the opening and closing bracket, try
[ $HOUR == 13 ] && [ $MINUTE == 12 ] && [ $SECOND == 1 ]
and
[ $HOUR == 18 ] && [ $MINUTE == 30 ] && [ $SECOND == 1 ]
here is a link that you might find useful
http://tldp.org/LDP/abs/html/testconstructs.html
Several things:
You have to put a space after [ and before ].
It's a good practice to protect your variables using double quotes.
You have to use the -eq operator to compare numeric values (see Bash conditional operators).
Like so:
if [ "$HOUR" -eq 13] && [ "$MINUTE" -eq 12 ] && [ "$SECOND" -eq 1 ]
elif [ "$HOUR" -eq 18 ] && [ "$MINUTE" -eq 30 ] && [ "$SECOND" -eq 1 ]
I read in tldp.com that
if [ $condition1 ] && [ $condition2 ]
Same as: if [ $condition1 -a $condition2 ]
Returns true if both condition1 and condition2 hold true..."
but when I tried
if [ $a == 2 ] || [ $b == 4 ]
then
echo "a or b is correct"
else
echo "a and b are not correct"
fi
it gives error. I'm using bash.
Your logic is ok but your comparison operators are incorrect, you should use the '-eq' for comparing integers and '==' for strings. See 'man test' for quick reference, though it's also documented in 'man bash'.
When using integer comparison it is always best to initialise variables to 0 as well otherwise if they remain unset you will get errors.
As mentioned by c00k, use [[ rather than [ if using bash as it is a builtin so bash will not need to shell out to use the /usr/bin/[ command.
i.e.
a=0;b=0
# do something else with a or b
if [[ $a -eq 2 ]] || [[ $b -eq 4 ]]
then
echo "a or b is correct"
else
echo "a and b are not correct"
fi
If you're using Bash, then drop the single [ and use double ones [[.
For arithmetic operations, use ((.
So you'd want to write this:
if (( a == 2 )) || (( b == 4 )); then
echo "foo"
fi # etc
Did you assign a value to a and b? If not you have to (otherwise you definitely should) quote your variables with double quotes:
if [ "$a" == "2" ] || [ "$b" == "4" ]; then
echo "a or b is correct";
else
echo "a and b are not correct";
fi
Correct me if I'm wrong. && and || are bash comparison
#!/usr/bin/ksh
set -x ###### debug mode on
while :
do
dt=`date '+%M'`
if ([ "$dt" -ge "15"] && [ "$dt" -le "17" ]) || ([ "$dt" -ge "25" ] && [ "$dt" -le "27" ])
then
echo "Time-->minutes between 15 to 17 OR 25 to 27"
else
echo "Time--> minutes out of range"
fi
sleep 300 ##### sleep for 5 minutes
done
------------- below lines are debug output
+ + date +%M
dt=17
+ [ 17 -ge 15 ]
+ [ 17 -le 17 ]
+ echo Time--> minutes between 15 to 17 OR 25 to 27
Time--> minutes between 15 to 17 OR 25 to 27
+ date
Sat Mar 3 15:17:23 AST 2012
+ sleep 300
>+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ :
+ + date +%M
dt=22
+ [ 22 -ge 15 ]
+ [ 22 -le 17 ]
+ [ 22 -ge 25 ]
+ echo Time--> minutes out of range
Time--> minutes out of range
+ sleep 300
^C$ ######## breaking out of loop(terminating the execution).
$
$ env |grep -i shell
+ grep -i shell
+ env
SHELL=/bin/ksh
$ set +x ##### ending debug mode.