I'm ALL NEW in shell script , hence have a question about how to round up integer.
Here is a line of the code from a script by keke(smstools3 developer)
balance=$(substr "$result" "$balance_prefix" "$balance_suffix")
And my balance is 111.12 , and I wish to round it up.
I tried
balance1=$(substr "$result" "$balance_prefix" "$balance_suffix")
balance=$("%0.f\n" "$balance1")
or
balance1=$(substr "$result" "$balance_prefix" "$balance_suffix")
balance=$(ceil($balance1))
Both refer from some answers after google it , I not even know if the syntax is correct.And of course both example return blank.
Any hints or advice?Thank you.
Edit:
# Check that required words exists:
if [[ "$result" == *${balance_prefix}* ]] && \
[[ "$result" == *${balance_suffix}* ]]
then
# Get the balance and check it:
balance=$(substr "$result" "$balance_prefix" "$balance_suffix")
balance_low=0
if [ $(expr "$balance" + 1 2> /dev/null) ]; then
[ $balance -le $alert_balance ] && balance_low=1
else
echo "Error while parsing an integer: $balance"
fi
else
echo "Error while parsing the answer (balance): $result"
fi
source : http://smstools3.kekekasvi.com/topic.php?id=320
balance=`python -c "from math import ceil; print(ceil($balance1))"`
or
balance=`perl -MPOSIX -e "print ceil($balance1)"`
Using only a minimum of standard tools (perl and python are quite common though):
balance=$(echo "x=${balance1}; scale=0; xx=x/1; if(x>xx) xx+=1; print xx"|bc -l)
Related
I want to write a short script to ssh to different servers depending on the argument I provide - if it is a number, I want the number to be a part of the server name, if it is a letter I want it connect to a certain server. So far I have this:
#!/bin/bash
if [ $1 -eq ^[1,3-5]$ ]; then
ssh -X servername1$1
elif [ $1=h ]; then
ssh -X servername2
fi
but it keeps complaining that integer expression is expected and always tries to connect to servername2, no matter whether I give it a number or a letter.
I tried quotation marks around the first and the second comparison, I tried double equality sign in the second comparison - all to no avail. How can I make this work?
[ $1 -eq ^[1,3-5]$ ] is not bash syntax.
You can write like that:
#!/bin/bash
if [[ $1 =~ ^[1,3-5]$ ]]; then
echo "$1 integer"
elif [ $1 = h ]; then
echo "$1 letter"
fi
Output:
[sahaquiel#sahaquiel-PC Stackoverflow]$ ./numorlet.sh 1
1 integer
[sahaquiel#sahaquiel-PC Stackoverflow]$ ./numorlet.sh 3
3 integer
[sahaquiel#sahaquiel-PC Stackoverflow]$ ./numorlet.sh 10
[sahaquiel#sahaquiel-PC Stackoverflow]$ ./numorlet.sh h
h letter
[sahaquiel#sahaquiel-PC Stackoverflow]$ ./numorlet.sh hhhh
[sahaquiel#sahaquiel-PC Stackoverflow]$
Also, tell me please, if the letter will be only 'h', or it can be any?
If any, use [[ instead of [ also in elif condition, with regex (I think ^[a-zA-Z]$ will work)
I suppose you have a server list where you are taking the argument $1 from.
If yes, you will have to do some changes in the code.
#!/bin/bash
if [[ $1 -eq ^[1,3-5]$ ]]; then
ssh -X servername1$1 < /dev/null
elif [[ $1==h ]]; then
ssh -X servername2 < /dev/null
fi
SSH takes input from stdin by adding input from /dev/null you are telling ssh to take input from that specific file.
Using [[...]] tells that if has an expression.
you can read more about the [[..]] in this link "Confused about operators"
Also $1=h is an assignment not a comparison; == is used for comparison.
I need to write a while loop to check for a file existence.
My requirement is: check for the file only for 5 minutes. If file come in that path within 5 minutes exit the loop and continue rest of the script otherwise exit from the script after 5 minutes with an error 'file not found'. I wrote the code like this :
SOURCEFILE=/path/*file.csv
StartTime=$(date +'%s')
TimeSpan=300
EndTime=$((StartTime + TimeSpan))
while [[ ! -f ${SOURCEFILE} && $(date +'%s') < ${EndTime} ]]
do
echo "inside loop"
sleep 25
done
echo "outside loop"
But with this while loop, even if the file is present in the mentioned path, it is going inside loop and will exit only after 300 seconds. I am beginner in shell scripting and I am not able to understand the issue. I am using ksh.
I could also tell you that it works find with while [ ! -f {SOURCEFILE} ] only. But whenever I add any && condition to while loop , then the -f is not working properly.
The SOURCEFILE=/path/*file.csv is wrong in your case. It can't be evaluated right with the -f flag.
An easy solution would be to use find or ls and count the result:
find /path/ -name "*file.csv" -type f
# then count the result...
Now I think there is a logic issue with the operators precedence. To force evaluation of the ! for the -f only, use parenthesis. Here is what works for me, and you must adapt it a little to match the * before file.csv:
while [[ ( ! -f file.csv ) && $(date +'%s') < ${EndTime} ]]
do
echo "inside loop"
sleep 25
...
There are some more explanation on this answer. The "and" operator precedes the "not", that's why you had the issue.
Your primary issue is getting the asterisk (*) to expand at the 'right time'.
It doesn't help that the [ ] and [[ ]] constructs behave differently, especially when it comes to if/when to expand that asterisk. [You can peruse the google search for 'ksh single bracket vs double bracket' for more details.]
Try running the following to see the differences between single/double brackets and unquoted/single-quoted/double-quoted variable:
SOURCEFILE=/path/*file.csv
set -x
[ ! -f ${SOURCEFILE} ] && echo 'missing'
[ ! -f '${SOURCEFILE}' ] && echo 'missing'
[ ! -f "${SOURCEFILE}" ] && echo 'missing'
[[ ! -f ${SOURCEFILE} ]] && echo 'missing'
[[ ! -f '${SOURCEFILE}' ]] && echo 'missing'
[[ ! -f "${SOURCEFILE}" ]] && echo 'missing'
NOTE: Notice which tests expand the asterisk and which are looking for a (literal) asterisk in the name.
NOTE: Try adding a space to your file name (eg, *file XX.csv) and run the above tests ... tricky, tricky, tricky ...
For this particular case ... asterisk/wildcard in file name, no spaces, ksh ... you'll likely be ok with something like:
while [[ ! -f ${SOURCEFILE} ]] && [[ $(date +'%s') < ${EndTime} ]]
I am very new here, so I apologize for any my mistakes, and I am sorry for my lack of knowledge (I'm just beginner).
So here it is, i am doing little script in bash with li and I have if statement, here it is
#!/bin/bash
something=$(whiptail --inputbox "Enter some text" 10 30 3>&1 1>&2 2>&3)
if [ $something ?? 'you' ];
then
echo "$something"
else
echo "nope"
fi
To be specific what i want from it - I enter some word/sentence/whatever to whiptail, and if it contains some of of you string then prints it, but every times it goes else ;_;.Please help.
EDIT now it works, thanks but I need to check if string contains word.
if [[ $string =~ .*My.* ]]
doesn't seem to work
I don't get it at all, losing hope and searching the web i've encontered on
#!/bin/bash
OPTION=$(whiptail –title “Menu Dialog” –menu “Choose your option” 15 60 4 \ “1” “Grilled ham” \ “2” “Swiss Cheese” \ “3” “Charcoal cooked Chicken thighs” \ “4” “Baked potatos” 3>&1 1>&2 2>&3)
exitstatus=$?
if [ $exitstatus = 0 ];
then echo “Your chosen option:” $OPTION
else echo “You chose Cancel.”
fi
And I've just pasted this script to check how it works and modify it, it isn't mine script and it supposed to work, but it says “You chose Cancel.”
What you may be looking for are the string comparison operators like == or !=. For example,
if [ "$something" == "you" ]; then
echo "$something"
else
echo "nope"
fi
If $something equals you then echo $something; else echo nope.
Or, as David C.Rankin mentioned in his comment you can check the string variable to prove whether a string is empty or not. For example,
if [ -z "$something"] ;then
String is empty
if [ -n "$something" ]; then
String is non-empty
For more information on this check the TEST manual page.
I am trying to compare to build numbers and echo which is greater. Here is a script i wrote
New_Cycle_Num='c4.10'
Old_Cycle_Num='c4.9'
if [ "$New_Cycle_Num" == "$Old_Cycle_Num" ];
then echo 'both are equal'
elif [ "$New_Cycle_Num" "<" "$Old_Cycle_Num" ]];
then echo 'New_Cycle_Num is less than Old_Cycle_Num'
else echo 'New_Cycle_Num is greater than Old_Cycle_Num'
fi
My script gives me ioutput as 'New_Cycle_Num is less than Old_Cycle_Num" instead of last statement. why is c4.10 compared to be less than c4.9? any help to correct this ?? Many thanks!!
You get the result you get because with lexical comparison, comparing the 4th character, "1" appears before "9" in the dictionary (in the same sense that "foobar" would appear before "food", even though "foobar" is longer).
Tools like ls and sort have a "version sorting" option, which will be useful here, albeit somewhat awkward:
New_Cycle_Num='c4.10'
Old_Cycle_Num='c4.9'
if [[ $New_Cycle_Num == $Old_Cycle_Num ]]; then
echo 'equal'
else
before=$(printf "%s\n" "$New_Cycle_Num" "$Old_Cycle_Num")
sorted=$(sort -V <<<"$before")
if [[ $before == $sorted ]]; then
echo 'New_Cycle_Num is less than Old_Cycle_Num'
else
echo 'New_Cycle_Num is greater than Old_Cycle_Num'
fi
fi
New_Cycle_Num is greater than Old_Cycle_Num
I can't think of a great alternative. There might be
echo -e "c4.10\nc4.9" |
perl -MSort::Versions -E '
$a=<>; $b=<>; chomp($a, $b); $c=versioncmp($a,$b);
say "$a is ". ($c==0 ? "equal to" : $c < 0 ? "less than" : "greater than") . " $b"
'
c4.10 is greater than c4.9
But you have to install Sort::Versions from CPAN.
I am making a bash script where I want to find files that are equal to a variable. The equals will then be used.
I want to use "mogrify" to shrink a couple of image files that have the same name as the ones i gather from a list (similar to "dpkg -l"). It is not "dpkg -l" I am using but it is similar. My problem is that it prints all the files not just the equals. I am pretty sure this could be done with awk instead of a for-loop but I do not know how.
prog="`dpkg -l | awk '{print $1}'`"
for file in $dirone* $dirtwo*
do
if [ "basename ${file}" = "${prog}" ]; then
echo ${file} are equal
else
echo ${file} are not equal
fi
done
Could you please help me get this working?
First, I think there's a small typo. if [ "basename ${file}" =... should have backticks inside the double quotes, just like the prog=... line at the top does.
Second, if $prog is a multi-line string (like dpkg -l) you can't really compare a filename to the entire list. Instead you have to compare one item at a time to the filename.
Here's an example using dpkg and /usr/bin
#!/bin/bash
progs="`dpkg -l | awk '{print $2}'`"
for file in /usr/bin/*
do
base=`basename ${file}`
for prog in ${progs}
do
if [ "${base}" = "${prog}" ]; then
echo "${file}" matches "${prog}"
fi
done
done
The condition "$file = $prog" is a single string. You should try "$file" = "$prog" instead.
The following transcript shows the fix:
pax> ls -1 qq*
qq
qq.c
qq.cpp
pax> export xx=qq.cpp
pax> for file in qq* ; do
if [[ "${file} = ${xx}" ]] ; then
echo .....${file} equal
else
echo .....${file} not equal
fi
done
.....qq equal
.....qq.c equal
.....qq.cpp equal
pax> for file in qq* ; do
if [[ "${file}" = "${xx}" ]] ; then
echo .....${file} equal
else
echo .....${file} not equal
fi
done
.....qq not equal
.....qq.c not equal
.....qq.cpp equal
You can see in the last bit of output that only qq.cpp is shown as equal since it's the only one that matches ${xx}.
The reason you're getting true is because that's what non-empty strings will give you:
pax> if [[ "" ]] ; then
echo .....equal
fi
pax> if [[ "x" ]] ; then
echo .....equal
fi
.....equal
That's because that form is the string length checking variation. From the bash manpage under CONDITIONAL EXPRESSIONS:
string
-n string
True if the length of string is non-zero.
Update:
The new code in your question won't quite work as expected. You need:
if [[ "$(basename ${file})" = "${prog}" ]]; then
to actually execute basename and use its output as the first part of the equality check.
you can use case/esac
case "$file" in
"$prog" ) echo "same";;
esac