I have d1="11" and d2="07". I want to convert d1 and d2 to integers and perform d1-d2. How do I do this in UNIX?

d1 - d2 currently returns "11-07" as result for me.

1

5 Answers

The standard solution:

 expr $d1 - $d2 

You can also do:

echo $(( d1 - d2 )) 

but beware that this will treat 07 as an octal number! (so 07 is the same as 7, but 010 is different than 10).

5

Any of these will work from the shell command line. bc is probably your most straight forward solution though.

Using bc:

$ echo "$d1 - $d2" | bc 

Using awk:

$ echo $d1 $d2 | awk '{print $1 - $2}' 

Using perl:

$ perl -E "say $d1 - $d2" 

Using Python:

$ python -c "print $d1 - $d2" 

all return

4 
3

An answer that is not limited to the OP's case

The title of the question leads people here, so I decided to answer that question for everyone else since the OP's described case was so limited.

TL;DR

I finally settled on writing a function.

  1. If you want 0 in case of non-int:
int(){ printf '%d' ${1:-} 2>/dev/null || :; } 
  1. If you want [empty_string] in case of non-int:
int(){ expr 0 + ${1:-} 2>/dev/null||:; } 
  1. If you want find the first int or [empty_string]:
int(){ expr ${1:-} : '[^0-9]*\([0-9]*\)' 2>/dev/null||:; } 
  1. If you want find the first int or 0:
# This is a combination of numbers 1 and 2 int(){ expr ${1:-} : '[^0-9]*\([0-9]*\)' 2>/dev/null||:; } 

If you want to get a non-zero status code on non-int, remove the ||: (aka or true) but leave the ;

Tests

# Wrapped in parens to call a subprocess and not `set` options in the main bash process # In other words, you can literally copy-paste this code block into your shell to test ( set -eu; tests=( 4 "5" "6foo" "bar7" "foo8.9bar" "baz" " " "" ) test(){ echo; type int; for test in "${tests[@]}"; do echo "got '$(int $test)' from '$test'"; done; echo "got '$(int)' with no argument"; } int(){ printf '%d' ${1:-} 2>/dev/null||:; }; test int(){ expr 0 + ${1:-} 2>/dev/null||:; } test int(){ expr ${1:-} : '[^0-9]*\([0-9]*\)' 2>/dev/null||:; } test int(){ printf '%d' $(expr ${1:-} : '[^0-9]*\([0-9]*\)' 2>/dev/null)||:; } test # unexpected inconsistent results from `bc` int(){ bc<<<"${1:-}" 2>/dev/null||:; } test ) 

Test output

int is a function int () { printf '%d' ${1:-} 2> /dev/null || : } got '4' from '4' got '5' from '5' got '0' from '6foo' got '0' from 'bar7' got '0' from 'foo8.9bar' got '0' from 'baz' got '0' from ' ' got '0' from '' got '0' with no argument int is a function int () { expr 0 + ${1:-} 2> /dev/null || : } got '4' from '4' got '5' from '5' got '' from '6foo' got '' from 'bar7' got '' from 'foo8.9bar' got '' from 'baz' got '' from ' ' got '' from '' got '' with no argument int is a function int () { expr ${1:-} : '[^0-9]*\([0-9]*\)' 2> /dev/null || : } got '4' from '4' got '5' from '5' got '6' from '6foo' got '7' from 'bar7' got '8' from 'foo8.9bar' got '' from 'baz' got '' from ' ' got '' from '' got '' with no argument int is a function int () { printf '%d' $(expr ${1:-} : '[^0-9]*\([0-9]*\)' 2>/dev/null) || : } got '4' from '4' got '5' from '5' got '6' from '6foo' got '7' from 'bar7' got '8' from 'foo8.9bar' got '0' from 'baz' got '0' from ' ' got '0' from '' got '0' with no argument int is a function int () { bc <<< "${1:-}" 2> /dev/null || : } got '4' from '4' got '5' from '5' got '' from '6foo' got '0' from 'bar7' got '' from 'foo8.9bar' got '0' from 'baz' got '' from ' ' got '' from '' got '' with no argument 

Note

I got sent down this rabbit hole because the accepted answer is not compatible with set -o nounset (aka set -u)

# This works $ ( number="3"; string="foo"; echo $((number)) $((string)); ) 3 0 # This doesn't $ ( set -u; number="3"; string="foo"; echo $((number)) $((string)); ) -bash: foo: unbound variable 
let d=d1-d2;echo $d; 

This should help.

1

Use this:

#include <stdlib.h> #include <string.h> int main() { const char *d1 = "11"; int d1int = atoi(d1); printf("d1 = %d\n", d1); return 0; } 

etc.

1

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy