How to compute exponentiation and roots in the shell? - shell

I'm a beginner in shell and linux in general, it's a Shell Arithmetic question and I can't figure out what to write in terminal to solve these three equations. I'm sorry if it seems a bad question, I tried echo command and expr, but all of them are wrong and with many different errors like, '(' , syntax error near..., E0F, and many other unfortunately. I hope someone will provide me with the correct commands. And I appreciate any help from you. I'll put down the terminal codes that I used which are wrong as I know.
$ x=8
$ y=21
$ echo $((2*x**3 + sqrt(y/2))
bash: unexpected EOF while looking for matching ')'
bash: syntax error: unexpected end of file
$ echo $((2*x**3) + (sqrt(y/2)))
bash: command substitution: line 1: syntax error near unexpected token +'
bash: command substitution: line 1: `(2*x**3) + (sqrt(y/2))'
$ echo $((2*x**3)+(sqrt(y/2))
bash: unexpected EOF while looking for matching )'
bash: syntax error: unexpected end of file
$ echo $((2*x**3)+(sqrt(y/2)))
bash: command substitution: line 1: syntax error near unexpected token +(sqrt(y/2))'
bash: command substitution: line 1: `(2*x**3)+(sqrt(y/2))'
$ echo $((2x**3)+(sqrt(y / 2)))
bash: command substitution: line 1: syntax error near unexpected token +(sqrt(y / 2))'
bash: command substitution: line 1: (2x**3)+(sqrt(y / 2))'

The shell is not the right tool to do floating point computations. It only does integer math and does not provide functions like square root.
However, the bc utility does both. It is an arbitrary-precision decimal arithmetic language and calculator.
$ bc
>>> scale=5
>>> sqrt(21)
4.58257
>>> scale=19
>>> sqrt(21)
4.5825756949558400065
>>> x=8
>>> y=21
>>> x+5
13
>>> x^2
64
>>> 2*x^2 - sqrt(y/2)
124.7596296507960698846
>>> Type Control-D to exit interactive bc.
$
Be sure to read the manual page for bc with man bc to understand all of its capabilities and limitations.

Related

subtract 2 (time) variables in makefile

I want to compute the time it takes to finish my command in makefile.
Here is what I tried, but it doesn't work:
FILE = some_file.6.txt
.ONESHELL:
another_file.txt: ${FILE}
#START=$$(date +%s.%N)
#END=$$(date +%s.%N)
#echo $$(($$END-$$START))
Here is the error I get:
$ make
/bin/sh: 3: arithmetic expression: expecting EOF: "1569658240.437512688-1569658240.436685866"
makefile:5: recipe for target 'another_file.txt' failed
make: *** [another_file.txt] Error 2
I've tried all combination of adding/removing both ( and $.
Please help, thanks.
This is not a makefile problem. It's a shell problem. This is trivially seen by running the command at a shell prompt rather than a makefile, and you'll get the same error:
$ /bin/sh -c 'echo $((1569658240.437512688-1569658240.436685866))'
/bin/sh: 1: arithmetic expression: expecting EOF: "1569658240.437512688-1569658240.436685866"
It's also an error in bash, so setting SHELL := /bin/bash won't help:
$ /bin/bash -c 'echo $((1569658240.437512688-1569658240.436685866))'
/bin/bash: 1569658240.437512688-1569658240.436685866: syntax error: invalid arithmetic operator (error token is ".437512688-1569658240.436685866")
If you check the documentation for your shell you'll see that arithmetic expressions only work on integer values, not floating point values as you're attempting above.
To perform more advanced math including on floating point values, you should investigate the bc program:
.ONESHELL:
another_file.txt: ${FILE}
#START=$$(date +%s.%N)
#END=$$(date +%s.%N)
#echo $$END-$$START | bc

Shell script error; unexpected [duplicate]

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 6 months ago.
Any idea of what the problem could be?
My code is:
#!/bin/bash
while :
do
echo "Press [CTRL+C] to stop.."
sleep 1
done
Saved it as .sh and ran bash file.sh
CentOS 6 32-bit
What is the issue? First time EVER using BASH, need it for a simple infinite loop on something.
Run cat -v file.sh.
You most likely have a carriage return or no-break space in your file. cat -v will show them as ^M and M-BM- or M- respectively. It will similarly show any other strange characters you might have gotten into your file.
Remove the Windows line breaks with
tr -d '\r' < file.sh > fixedfile.sh
I was getting the same error on Cygwin; I did the following (one of them fixed it):
Converted TABS to SPACES
ran dos2unix on the .(ba)sh file
What is the error you're getting?
$ bash file.sh
test.sh: line 8: syntax error: unexpected end of file
If you get that error, you may have bad line endings. Unix uses <LF> at the end of the file while Windows uses <CR><LF>. That <CR> character gets interpreted as a character.
You can use od -a test.sh to see the invisible characters in the file.
$ od -a test.sh
0000000 # ! / b i n / b a s h cr nl # sp cr
0000020 nl w h i l e sp : cr nl d o cr nl sp sp
0000040 sp sp e c h o sp " P r e s s sp [ C
0000060 T R L + C ] sp t o sp s t o p " cr
0000100 nl sp sp sp sp s l e e p sp 1 cr nl d o
0000120 n e cr nl
0000124
The sp stands for space, the ht stands for tab, the cr stands for <CR> and the nl stands for <LF>. Note that all of the lines end with cr followed by a nl character.
You can also use cat -v test.sh if your cat command takes the -v parameter.
If you have dos2unix on your box, you can use that command to fix your file:
$ dos2unix test.sh
There's a way you can get this problem without having mixed newline problems (at least, in my shell, which is GNU bash v4.3.30):
#!/bin/bash
# foo.sh
function foo() {
echo "I am quoting a thing `$1' inside a function."
}
while [ "$input" != "y" ]; do
read -p "Hit `y' to continue: " -n 1 input
echo
done
foo "What could possibly go wrong?"
$ ./foo.sh
./foo.sh: line 11: syntax error near unexpected token `done'
./foo.sh: line 11: `done'
This is because bash expands backticks inside double-quoted strings (see the bash manual on quoting and command substitution), and before finding a matching backtick, will interpret any additional double quotes as part of the command substitution:
$ echo "Command substitution happens inside double-quoted strings: `ls`"
Command substitution happens inside double-quoted strings: foo.sh
$ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`"
..even with double quotes: foo "What could possibly go wrong?"
You can get around this by escaping the backticks in your string with a backslash, or by using a single-quoted string.
I'm not really sure why this only gives the one error message, but I think it has to do with the function definition:
#!/bin/bash
# a.sh
function a() {
echo "Thing's `quoted'"
}
a
while true; do
echo "Other `quote'"
done
#!/bin/bash
# b.sh
echo "Thing's `quoted'"
while true; do
echo "Other `quote'"
done
$ ./a.sh
./a.sh: line 10: syntax error near unexpected token `done'
./a.sh: line 10: `done'
$ ./b.sh
./b.sh: command substitution: line 6: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 9: syntax error: unexpected end of file
Thing's quote'
./b.sh: line 7: syntax error near unexpected token `done'
./b.sh: line 7: `done'
Might help someone else : I encountered the same kind of issues while I had done some "copy-paste" from a side Microsoft Word document, where I took notes, to my shell script(s).
Re-writing, manually, the exact same code in the script just solved this.
It was quite un-understandable at first, I think Word's hidden characters and/or formatting were the issue. Obvious but not see-able ... I lost about one hour on this (I'm no shell expert, as you might guess ...)
Sometimes this error happens because of unexpected CR characters in file, usually because the file was generated on a Windows system which uses CR line endings. You can fix this by running os2unix or tr, for example:
tr -d '\015' < yourscript.sh > newscript.sh
This removes any CR characters from the file.
Open new file named foobar
nano -w foobar
Input script
#!/bin/bash
while [ 0 = 0 ]; do
echo "Press [CTRL+C] to stop.."
sleep 1
done;
Exit and save
CTRL+X then Y and Enter
Set script executable and run
chmod +x foobar
./foobar
Had similar problems just now and these are two separate instances and solutions that worked for me:
Case 1. Basically, had a space after the last command within my newline-separated for-loop, eg. (imagining that | here represents the carat in a text editor showing where you are writing), this is what I saw when clicking around the end of the line of the last command in the loop:
for f in $pathToFiles
do
$stuff |
done
Notice the space before before the carat (so far as I know, this is something cat has no option do display visually (one way you could test is with something like od -bc yourscript.sh)). Changing the code to
for f in $pathToFiles
do
$stuff| <--- notice the carat shows no ending space before the newline
done
fixed the problem.
Case 2. Was using a pseudo try-catch block for the for-loop (see https://stackoverflow.com/a/22010339/8236733) like
{
for f in $pathToFiles
do
{ $stuff } || { echo "Failed to complete stuff"; exit 255; }
done
} || { echo "Failed to complete loop"; exit 255; }
and apparently bash did not like the nested {}s. Changing to
{
for f in $pathToFiles
do
$stuff
done
} || { echo "Failed to complete loop"; exit 255; }
fixed the problem in this case. If anyone can further explain either of these cases, please let me know more about them in the comments.
I had same problem, but solved.
I removed the following line in .bashrc
alias do="docker.exe" # this line caused the problem
I use WSL(windows subsystem for linux)
In my case, what was causing the problem was an if else statement. After re-writing the conditions, the error 'near done' got away.
Edit your code in any linux environment then you won't face this problem. If edit in windows
notepad any space take it as ^M.
I have exactly the same issue as above, and took me the whole day to discover that it doesn't like my newline approach. Instead I reused the same code with semi-colon approach instead.
For example my initial code using the newline (which threw the same error as yours):
Y=1
while test "$Y" -le "20"
do
echo "Number $Y"
Y=$[Y+1]
done
And using code with semicolon approach with worked wonder:
Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done
I notice the same problem occurs for other commands as well using the newline approach, so I think I am gonna stick to using semicolon for my future code.
For me you had to have it do something between the do and done.
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
done
echo "Loop Ended"
gave me the error, but
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
sleep 1
done
echo "Loop Ended"
fixed it.

Bash Syntax Error. Simple script [duplicate]

This question already has answers here:
Are shell scripts sensitive to encoding and line endings?
(14 answers)
Closed 6 months ago.
Any idea of what the problem could be?
My code is:
#!/bin/bash
while :
do
echo "Press [CTRL+C] to stop.."
sleep 1
done
Saved it as .sh and ran bash file.sh
CentOS 6 32-bit
What is the issue? First time EVER using BASH, need it for a simple infinite loop on something.
Run cat -v file.sh.
You most likely have a carriage return or no-break space in your file. cat -v will show them as ^M and M-BM- or M- respectively. It will similarly show any other strange characters you might have gotten into your file.
Remove the Windows line breaks with
tr -d '\r' < file.sh > fixedfile.sh
I was getting the same error on Cygwin; I did the following (one of them fixed it):
Converted TABS to SPACES
ran dos2unix on the .(ba)sh file
What is the error you're getting?
$ bash file.sh
test.sh: line 8: syntax error: unexpected end of file
If you get that error, you may have bad line endings. Unix uses <LF> at the end of the file while Windows uses <CR><LF>. That <CR> character gets interpreted as a character.
You can use od -a test.sh to see the invisible characters in the file.
$ od -a test.sh
0000000 # ! / b i n / b a s h cr nl # sp cr
0000020 nl w h i l e sp : cr nl d o cr nl sp sp
0000040 sp sp e c h o sp " P r e s s sp [ C
0000060 T R L + C ] sp t o sp s t o p " cr
0000100 nl sp sp sp sp s l e e p sp 1 cr nl d o
0000120 n e cr nl
0000124
The sp stands for space, the ht stands for tab, the cr stands for <CR> and the nl stands for <LF>. Note that all of the lines end with cr followed by a nl character.
You can also use cat -v test.sh if your cat command takes the -v parameter.
If you have dos2unix on your box, you can use that command to fix your file:
$ dos2unix test.sh
There's a way you can get this problem without having mixed newline problems (at least, in my shell, which is GNU bash v4.3.30):
#!/bin/bash
# foo.sh
function foo() {
echo "I am quoting a thing `$1' inside a function."
}
while [ "$input" != "y" ]; do
read -p "Hit `y' to continue: " -n 1 input
echo
done
foo "What could possibly go wrong?"
$ ./foo.sh
./foo.sh: line 11: syntax error near unexpected token `done'
./foo.sh: line 11: `done'
This is because bash expands backticks inside double-quoted strings (see the bash manual on quoting and command substitution), and before finding a matching backtick, will interpret any additional double quotes as part of the command substitution:
$ echo "Command substitution happens inside double-quoted strings: `ls`"
Command substitution happens inside double-quoted strings: foo.sh
$ echo "..even with double quotes: `grep -E "^foo|wrong" foo.sh`"
..even with double quotes: foo "What could possibly go wrong?"
You can get around this by escaping the backticks in your string with a backslash, or by using a single-quoted string.
I'm not really sure why this only gives the one error message, but I think it has to do with the function definition:
#!/bin/bash
# a.sh
function a() {
echo "Thing's `quoted'"
}
a
while true; do
echo "Other `quote'"
done
#!/bin/bash
# b.sh
echo "Thing's `quoted'"
while true; do
echo "Other `quote'"
done
$ ./a.sh
./a.sh: line 10: syntax error near unexpected token `done'
./a.sh: line 10: `done'
$ ./b.sh
./b.sh: command substitution: line 6: unexpected EOF while looking for matching `''
./b.sh: command substitution: line 9: syntax error: unexpected end of file
Thing's quote'
./b.sh: line 7: syntax error near unexpected token `done'
./b.sh: line 7: `done'
Might help someone else : I encountered the same kind of issues while I had done some "copy-paste" from a side Microsoft Word document, where I took notes, to my shell script(s).
Re-writing, manually, the exact same code in the script just solved this.
It was quite un-understandable at first, I think Word's hidden characters and/or formatting were the issue. Obvious but not see-able ... I lost about one hour on this (I'm no shell expert, as you might guess ...)
Sometimes this error happens because of unexpected CR characters in file, usually because the file was generated on a Windows system which uses CR line endings. You can fix this by running os2unix or tr, for example:
tr -d '\015' < yourscript.sh > newscript.sh
This removes any CR characters from the file.
Open new file named foobar
nano -w foobar
Input script
#!/bin/bash
while [ 0 = 0 ]; do
echo "Press [CTRL+C] to stop.."
sleep 1
done;
Exit and save
CTRL+X then Y and Enter
Set script executable and run
chmod +x foobar
./foobar
Had similar problems just now and these are two separate instances and solutions that worked for me:
Case 1. Basically, had a space after the last command within my newline-separated for-loop, eg. (imagining that | here represents the carat in a text editor showing where you are writing), this is what I saw when clicking around the end of the line of the last command in the loop:
for f in $pathToFiles
do
$stuff |
done
Notice the space before before the carat (so far as I know, this is something cat has no option do display visually (one way you could test is with something like od -bc yourscript.sh)). Changing the code to
for f in $pathToFiles
do
$stuff| <--- notice the carat shows no ending space before the newline
done
fixed the problem.
Case 2. Was using a pseudo try-catch block for the for-loop (see https://stackoverflow.com/a/22010339/8236733) like
{
for f in $pathToFiles
do
{ $stuff } || { echo "Failed to complete stuff"; exit 255; }
done
} || { echo "Failed to complete loop"; exit 255; }
and apparently bash did not like the nested {}s. Changing to
{
for f in $pathToFiles
do
$stuff
done
} || { echo "Failed to complete loop"; exit 255; }
fixed the problem in this case. If anyone can further explain either of these cases, please let me know more about them in the comments.
I had same problem, but solved.
I removed the following line in .bashrc
alias do="docker.exe" # this line caused the problem
I use WSL(windows subsystem for linux)
In my case, what was causing the problem was an if else statement. After re-writing the conditions, the error 'near done' got away.
Edit your code in any linux environment then you won't face this problem. If edit in windows
notepad any space take it as ^M.
I have exactly the same issue as above, and took me the whole day to discover that it doesn't like my newline approach. Instead I reused the same code with semi-colon approach instead.
For example my initial code using the newline (which threw the same error as yours):
Y=1
while test "$Y" -le "20"
do
echo "Number $Y"
Y=$[Y+1]
done
And using code with semicolon approach with worked wonder:
Y=1 ; while test "$Y" -le "20"; do echo "Number $Y"; Y=$[Y+1] ; done
I notice the same problem occurs for other commands as well using the newline approach, so I think I am gonna stick to using semicolon for my future code.
For me you had to have it do something between the do and done.
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
done
echo "Loop Ended"
gave me the error, but
#!/bin/bash
echo "Endless Loop, to STOP press ctrl C or ctrl Z"
for ((; ;))
do
sleep 1
done
echo "Loop Ended"
fixed it.

Syntax error running command bc under bash 4.1

I have a bash script with the following line. The variables start_time and start_files[$i] are floating point numbers. I want to compare them using the command bc as follows:
result1=$(bc -l <<< $start_time'>='${start_files[$i]})
When I run the script I always receive the following error.
(standard_in) 1: syntax error
I've checked that this error is due to this line. What am I doing wrong? The thing that this happens to me when using bash 4.1, with bash 4.3 runs fine. However I need to run the script with bash 4.1.
The bc command works however the input doesn't work. The variable start_files is read from a file with this command
IFS=, read -r -a start_files <<< $(head -n 1 file.txt)
Basically I want to read all the values from the first line separated by a coma and store them to different positions of the array. However using bash 4.1 all the values end up stored in start_files[0]. How can I solve this? This lines works for bash 4.3
I would suggest that you use double quotes:
result1=$(bc -l <<<"$start_time >= ${start_files[$i]}")
This way, you are echoing a single string to bc, containing your variables.
Are you reading the values from a file with DOS-style line endings perhaps?
$ start_time=$'1.5\r'
$ i=1
$ start_files[$i]=$'2.5\r'
$ bc -l <<< "$start_time >= ${start_files[$i]}"
(standard_in) 1: illegal character: ^M
(standard_in) 1: illegal character: ^M
You may avoid the here-string, add double quotes and remove a $:
result1=$(echo "$start_time >= ${start_files[i]}" | bc -l)
It would help to give the version of bc you're using. I'd guess it's not the same on the two systems. By the way, your error has nothing to do with Bash.
POSIX bc clearly states that a comparison (referred to as relational_expression in POSIX' bc Specification can only appear in a while, for or if construct.
So, first thing you'll try is this:
bc <<< "if($start_time >= ${start_files[$i]}) 1 else 0"
This might not work, as POSIX' bc doesn't allow an else clause in an if statement. (As amazing as it may seem, you read that last sentence correctly).
If your bc is really POSIX stuck up, then you'll have to do some ugly stuff as, e.g.,
bc <<< "ret=0; if($start_time >= ${start_files[$i]}) { ret=1 } ret"
or even something worse (sorry, I don't have a POSIX bc here, so I can't experiment—if someone has one at hand or remembers the syntax off the top of his head, please edit this line with the proper syntax).
Good luck!

syntax error near unexpected token `(' in below code

I have very small shell script.When I am running it run flow. it is giving "syntax error near unexpected token `(". Very basic question but sorry not able to figure out.
foreach i ( `cat list407`)
mkdir cells/${i}
cp /<path>/$i/${i}.gds cells/${i}/${i}.gds
end
Error:
flow: line 1: syntax error near unexpected token `('
flow: line 1: `foreach i ( `cat list407`)'
You've used csh syntax for execution using bash which is causing the error.
Either use csh to execute your script, or using bash say:
while read -r i; do
mkdir "cells/${i}"
cp "/<path>/${i}/${i}.gds" "cells/${i}/${i}.gds"
done < list407
for i in $(cat list407); do
mkdir cells/${i};
cp /<path>/$i/${i}.gds cells/${i}/${i}.gds;
done

Resources