How to handle floating point division for large numbers using bc in bash? [duplicate] - bc

This question already has answers here:
How to get bc to handle numbers in scientific (aka exponential) notation?
(11 answers)
Closed 2 years ago.
I am trying to calculate percentages with large numbers using the exponential notation. However, when doing this on bash using bc, I get what I presume to be is overflow errors.
For example, in bash if I do the calculation:
$ echo "6139391.0 / 2.9960647E7" | bc -l
2049151.60918664203376373104
The calculation is off. It should be 0.20491516755.
How do I handle cases like this using bc or bash in general?

Overflow? 
No; it's just ignoring the exponent; it's giving you 6139391.0 / 2.9960647.
Try
echo "6139391.0 / 2.9960647E7" | sed -E 's/([0-9.]*)E([+-]*[0-9]*)/(\1*10^\2)/g' | bc -l
to convert 2.9960647E7 to (2.9960647*10^7).

bc does not support scientific notation, see this answer for a workaround.

Related

Extract JSON value in Bash [duplicate]

This question already has answers here:
Read JSON data in a shell script [duplicate]
(4 answers)
Closed 6 years ago.
In the Bash I saved response data into a variable.
The result looks like this:
{"token_type":"Bearer","access_token":"022-8baa5324-f57b-445d-c5ec-821c63a5fd35","expires_in":3600,"scope":"any-website.com"}
Now I want to extract the value of the access token into an other var.
In Linux I solved that in this way and it works:
echo "$response_json" | grep -oP '(?<="access_token":")[^"]*'
As result I get:
022-8baa5324-f57b-445d-c5ec-821c63a5fd35
My problem is that MacOS does not support the grep parameter P (Perl expression) anymore. Parameter E does not work with that expression.
I would appreciate any help with a solution without requiring to install additional Bash tools.
Everyone says they don't want to install new tools, but really, line-oriented tools like grep simply weren't designed to cope with structured text like JSON. If you are going to work with JSON, get tools designed to process it.
jq is one such option:
$ echo "$response_json" | jq -r '.access_token'
022-8baa5324-f57b-445d-c5ec-821c63a5fd35

Regex variable in bash [duplicate]

This question already has answers here:
Parsing JSON with Unix tools
(45 answers)
Closed 7 years ago.
How extract specific data from my variable in Bash ?
myvar={"tag":"somedata", "token":"dataIWant", "...":"..."};
I 'm not very comfortable with unix command, specially regex.
Taking kojiro's suggestion:
myvar=$( curl ... )
value=$( jq -r '.token' <<< "$myvar" )
echo "$value" # ==> dataIWant

Replacing ascii with matching characters using perl / awk or other [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I have an access log that was written with nginx and lua code.
It is url encoded and those some characters are written in the format of \xHexCode (for example, double quotes are written as \x22).
I would like to run awk or perl or other fast script to replace it back.
You can use gnu-awk like this:
str='\x22 \x41 written as \x22).'
awk -v RS='\\\\x[0-9]+' 'RT{ORS=sprintf("%c", strtonum("0" substr(RT, 2)))} 1' <<< "$str"
" A written as ").
This is how it is working:
Using RS='\\\\x[0-9]+' we're separating custom record separator for each of those \xNN numbers.
substr(RT, 2) takes x41 from \x41
strtonum("0" substr(RT, 2)) adds 0 to make it 0x41 and returns ascii code 65.
printf "%c" prints equivalent ascii character A from 65.
ORS=... sets output record separator same as the return value of sprintf.

Move files starting with number and of type pdf [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am just a beginner in regex, so please forgive me if this question is too easy.
What I want to ask is that I have a bunch of files in a directory and I move some of the files which start with numbers and of type pdf. How to use regex with mv command and what would be the regex.
If you're using linux command prompt, actually you're not using Regex, but you're using GLOB notation instead, which is different. Read up on that. GLOB cannot take complex pattern such as the one you describe. You need to use real regex.
For your case, you can use grep command on the output of ls to find the files meeting your requirement, then call mv on them. Something like this:
while read fileName; do mv $fileName destination_folder; done < <(ls -1 | grep -E '[0-9].*\.pdf')
Let's break it up:
while read fileName; do
mv $fileName destination_folder;
done < <(ls -1 | grep -E '[0-9].*\.pdf')
So basically you read through the directory listing using while loop, which gets the input from the output of the last line ls -1 | grep -E '[0-9].*\.pdf'. Using while loop (instead of simpler for loop) is necessary to cater filenames containing spaces.
Now the command ls -1 | grep -E '[0-9].*\.pdf' basically just list down the filenames, and grab only those matching specified RegEx pattern.
You could use find too:
find . -maxdepth 1 -name "[0-9]*.pdf" -exec mv {} destination \;

compare two files containing doubles

I want to check equality of two files containing double numbers.
I should consider near numbers equal e.g. differences of at most 0.0001.
It's easy to write a tester for that with C but is there an easier way? e.g. bash commands?
Here is one way you can do it:
paste file1 file2 | awk '{d=$1-$2;if((d<0?-1*d:d)>0.0001) print $0 " " d }'
First use paste to print out corresponding lines. Then pass them to awk to subtract. Calculate the absolute difference and check if it is more than your tolerance of 0.00001. If so, print out both values and the difference.
Bash does not provide operators for floating point manipulations. You can look up bc and it should be fairly easy to integrate it in a bash script.
See this article on Linux Journal. That should provide you with a starting point. It is upto you to work through the file structure.