DenisZ
DenisZ

Reputation: 331

Bash parameter expansion from both sides

I'm getting dollar values from a file into the variable in the form p=$1234.56, and would like remove $ and decimal places to get integer value in my conditional like

if [[ ${p%%.*} < 1000]]; then p=${p}0; fi

But this doesn't remove the $ sign, and I don't want to do it in 2 steps and modify actual variable, as I need $ for later use. How to get integer value regardless of number of digits ie ($2.2, $123456.1234...)?

Upvotes: 1

Views: 502

Answers (3)

tshiono
tshiono

Reputation: 22062

Another option will be to use cut command to extract the substring before the dot (if any). Then you can say something like:

p='$1234.56'
[[ $(cut -d. -f1 <<< "${p#\$}") < 1000 ]] && p=${p}0
echo "$p"

BTW the expression [[ str1 < str2 ]] performs lexicographical comparison, meaning [[ 20 < 1000 ]] returns false because 20 sorts after 1000 in dictionary order.

If what you want to do is arithmetic comparison, you'll need to say [[ val1 -le val2 ]] or (( val1 < val2 )) such as:

p='$1234.56'
[[ $(cut -d. -f1 <<< "${p#\$}") -le 1000 ]] && p=${p}0
echo "$p"

Upvotes: 0

Ivan
Ivan

Reputation: 7317

It's not possible without modifying the var. But you can use a subshell process with something like sed

if [[ $(sed 's/\$\([0-9]*\)\..*/\1/' <<< $p) < 1000 ]]; then p=${p}0; fi

Upvotes: 1

tripleee
tripleee

Reputation: 189799

Unfortunately, there is no way to avoid performing multiple parameter expansions if you need to remove multiple patterns, in the general case.

In simple cases like this, you can avoid a temporary variable just by assigning back to the same variable.

p=${p#\$}
p=${p%.??}

In your specific scenario, of course, you can just replace any nonnumeric characters globally, and accept that the number will be multiplied by 100. You will obviously then need to multiply the number you compare against correspondingly.

if [[ ${p//[!0-9]/} < 100000 ]]

Of course, for this to work, you need to be sure that your variable's value conforms to your expectations. If the value could have different numbers of decimal places depending on what a user passes in or where you read the input from, you need to perform additional normalizations, or just use a different approach entirely (frequently you'd pass your input to Awk or bc which support floating point math, unlike the shell).

However, the string substitution parameter expansion ${variable//pattern/replacement} is a Bash extension, and not portable to Bourne/POSIX sh.

Upvotes: 1

Related Questions