I am trying to write a loop that uses command line arguments to determine the range over which it operates. As of now I've tried the following:
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g = $((20 - i))
echo $bwd_g
done
when I call ./test.sh the following output is produced:
./test.sh: line 9: let: =: syntax error: operand expected (error token is "=")
I've spent a large amount of time on coming up with different variants of this code but to no avail and have tried googling the error message.
Though I am not fully sure about your requirement, but to fix your specific error, try wrapping let with " and it should fly then, like (there shouldn't be any spaces between variable name(s) and =):
cat script.sh
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let "bwd_g = $((20 - i))"
echo $bwd_g
done
You should use $((.....)) for doing operations in bash, so better use following rather than let:
cat script.sh
a=$1
best=$2
for ((i=a ; i < best ; i++)); do
bwd_g=$((20 - i))
echo $bwd_g
done
I think the issue was with blank spaces on line 4. Please check below.
let a=$1
let best=$2
for ((i=a ; i < best ; i++)); do
let bwd_g=$((20 - i))
echo $bwd_g
done
and I ran it as
bash script.sh 5 10
Related
I would like to compare a number, which is the output of a command, with a constant and do some manipulation. That is, if $id < 10, I want to see 590$id and if it is above 10, I want to see 59$id.
I found that expr doesn't working here:
ID=3
NUM=59$ID
if [ `expr $ID` -lt 10]; then
NUM=590$ID
fi
echo $NUM
The output of the code is 593 and not 5903. Even, $(($ID + 5900)) -lt 5910 writes 593.
How can I fix that?
Could you please try following.
cat script.sh
#!/bin/bash
ID=$(printf "%02d" 3 )
##NUM=59$ID ##Commented this to check if, condition is getting satisfied or not. Doesn't seem to be fit here.
(( $ID < 10 )) && NUM="59$ID"
echo "$NUM"
Output will be 5903 after running above code.
Don't use expr. It's old and tricky.
Don't use backticks `. They are discouraged and $( ... ) is preferred.
For arithmetic comparisons use arithmetic expansions. Just
if (( ID < 10 )); then
Note that bash is space aware and your script has a syntax error, it is missing a space - the 10]; should be 10 ];.
Note that by convention uppercase variables should be used for exported variables.
Looking at your code I think you just want:
NUM=$((5900 + ID))
This question already has answers here:
call bash script and fill input data from another bash script
(2 answers)
Closed 4 years ago.
I have this bash script that runs calculus operations for me. It starts off with "read"...
How can I make Script A enter a value into Script B, read the output and dismiss Script B again?
Example:
#ScriptA.sh
a=12
b=4
[open Script B, enter $a and $b and read the result]
echo "The result is [the result of Script B]."
#ScriptB.sh
read x y
echo $(($x+$y))
Desired Output:
bash ScriptA.sh
The result is 16.
Of course it's about more complex maths but you get the idea. Note that, for convenience purposes, I don't want to change the structure of Script B (read x y). But I hope that there are some guys here that can solve this problem.
Thanks in advance.
You should do something like this:
#!/bin/bash
a=12
b=4
result=$(echo $a $b | ./script_b.sh)
echo "the result is $result"
Script B should work like -bc does.
Example:
echo `echo "4^3.5" | -scriptb.sh`
[result]
Edit: I just came up with a part of the solution by myself and thought I'd share it:
# ScriptA.sh
echo `echo "44 33" | bash ScriptB.sh`
# ScriptB.sh
read x y
echo $(($x+$y))
Output:
bash ScriptA.sh
77
The next problem is my ScriptB.sh looks a little more like this:
# ScriptB.sh
until [[ 1 = 2 ]]; do
echo Enter x and y
read x y
if [[ x = q ]]; then
break 1
fi
echo $(($x+$y))
done
This is in order to allow multiple inputs, if I want to use ScriptB manually. If I let ScriptA use ScriptB in the above mentioned way the output looks like this:
bash ScriptA.sh
b.sh: line 9: +: syntax error: operand expected (error token is "+")
Enter x and y 77 Enter x and y
It seems to be the case that after ScriptA inputs 44 and 33 and hits enter, like it should, but it hits enter right away a second time triggering the syntax error message and ending ScriptB. This is suboptimal, because in the case of the real ScriptB it will enter a "(standard_in) 1: parse error"-chain, resulting in no result at all. The solution to this problem would be by teaching ScriptA to read what ScriptB promts as result and ending it right after this. Or making it enter "q" as a second input instead of just hitting enter.
Edit 2:
Ok. Got it. Script A should look like this in order to work as desired:
e=2.7182818285
pi=3.141
a=$(printf "$e $pi \n q \n" | bash ScriptB.sh)
a=${a:14:20}
echo $a
I am trying to calculate the sum of numbers entered via command line to my script file. Here is my code
#!/bin/bash
for ((i=0;i<=$#;i++))
do
sum=$(($i + $sum))
done
echo $sum | bc
My terminal input is
bash file.sh 1 2
So the output should be 3 but I am getting
syntax error: operand expected (error token is "+ ")
The actual error reason is because of uninitialized variable sum going through the first iteration of the loop. Initialize the variable before entering the loop.
Also a major logical flaw is that you are not even iterating over the input arguments, but just over the counter i which will produce incorrect results if you pass arguments other than 1 2 from the command-line.
You need to pass over the actual arguments argc and argv (arg count and arg vector: for understanding purposes only) and you don't need bc at all
argc=$#
argv=("$#")
sum=0
for ((i=0; i<${argc}; i++)); do
sum=$((${argv[i]} + $sum))
done
To loop over all command line arguments, you can use the simplified form of the shell for statement:
sum=0
for i do
((sum += i))
done
((sum+=i)) is accepted by bash and many other shells; for a Posix-compatible shell, you can use arithmetic expansion with the : builtin:
: $((sum += i))
I have a side-project in BASH for fun, and I have this code snippet (ARRAY[0] is 8):
while [ $ALIVE == true ]; do
$ARRAY[0] = ${ARRAY[0]} - 1
echo ${ARRAY[0]}
done
However, it comes back with this error:
line 16: 8[1]: command not found
I just started working in BASH, so I might be making an obvious mistake, but I've searched and searched for an answer to a problem like this and came up with no result.
The smallest change is simply:
ARRAY[0]=$(( ${ARRAY[0]} - 1 ))
Note:
No $ before the name of the variable to assign to (foo=, not $foo=)
No spaces around the = on the assignment
$(( )) is the syntax to enter a math context (and expand to the result of that operation).
The below bash script is written for finding the files which are modified with in the last T second where T is supplied from the command line.
if [ $# -ne 1 ]; then
echo "Wrong number of argument"
exit 1
fi
for f in *
do
if [ -x "$f" ]; then
currenttime=$(date | awk '{print $4}')
modify=$(date -r "$f" | awk '{print $4}')
d_c=${currenttime:0:2}
m_c=${currenttime:3:2}
s_c=${currenttime:6:2}
d_m=${modify:0:2}
m_m=${modify:3:2}
s_m=${modify:6:2}
let "1d_c *= 24"
let "m_c *= 60"
let "second_c = d_c+m_c+s_c"
let "d_m *= 24"
let "m_m *= 60"
let "second_m=d_m+m_m+s_m"
let "diff=second_c-second_m"
if [ $diff -lt $1 ]; then
echo $f
fi
fi
do
ne
But I am getting the below error in that.
./recent.sh: line 46: let: 09: value too great for base (error token is "09")
./recent.sh: line 47: let: 09: value too great for base (error token is "09")
./recent.sh: line 49: let: 09: value too great for base (error token is "09")
I know that this error is coming due to the large value in the variable and I have to make the variable decimal but I don't know how to do it in my case(inside the let command, how to make them decimal).
The problem is that 09, due to the leading 0, is interpreted as octal, whereas (as you've surmised) you need it to be interpreted as decimal.
To fix this, you need to bypass let's normal convert-variable-to-number process. Instead of writing, for example, this:
let "second_c = d_c+m_c+s_c"
you should write this:
let "second_c = 10#$d_c + 10#$m_c + 10#$s_c"
By prepending $, you're asking Bash to substitute in the variable-value as a string — so, for example, if d_c is 09, then 10#$d_c will be 10#09. The 10# prefix tells let that the number should be interpreted as base-10.
Actually, on second thought, it's probably best to do this when you initially populate these variables; for example:
d_c=$(( 10#${currenttime:0:2} ))
That way you don't have to do it everywhere that you use them. (And also, it puts any errors closer to their source, which makes debugging easier.)