Multiply in bash script according to mattresses

So, I have an exercise in which I need to calculate a specific string.

For example, the string "|| x ||| + ||". The vertical lines are 1. So the solution to this line should be 8. So I made this script:

#!/bin/bash
result=$(echo $1 | tr -d ' ' | sed 's/|/1+/g' | sed 's/++/+/g' | sed 's/+x/x/g' | sed 's/ sed 's/x/*/g' | sed 's/+$//' | sed 's/$/\n/' | bc)

But when I ran this script in the sample line, I got 6. Then I realized, because the script is doing this: 1 + 1 * 1 + 1 + 1 + 1 + 1. Therefore, I need to make the brackets between (1 + 1) * (1 + 1 + 1) + (1 + 1), but I can’t figure it out.

Can someone help me? Thank you in advance!

+4
source share
5 answers

If you want to stick with sed, it's best to put in parens before the rest:

result=$(echo $1 | tr -d ' ' | sed -e 's/\(|*\)/(\1)/g' -e 's/|/1+/g' -e 's/+)/)/g' -e 's/x/*/g' | bc)
+3

, , :

{
echo "|x|+|"
echo "| x | + |"
echo "|| x ||| + ||"
echo "||x ||| +||"
echo "((|||x|||||-||||||)+|)/||"
echo "(((|||x|||||-||||||)+|)/||)^|||||"
} |
sed -e 's/||*/&)/g' \
    -e 's/|\(|*\)/(1\1/g' \
    -e 's/|/+1/g' \
    -e 's/x/*/g' |
tee converted.log |
bc

:

$ bash calc.sh
2
2
8
8
5
3125
$

converted.log:

(1)*(1)+(1)
(1) * (1) + (1)
(1+1) * (1+1+1) + (1+1)
(1+1)* (1+1+1) +(1+1)
(((1+1+1)*(1+1+1+1+1)-(1+1+1+1+1+1))+(1))/(1+1)
((((1+1+1)*(1+1+1+1+1)-(1+1+1+1+1+1))+(1))/(1+1))^(1+1+1+1+1)

sed script ; (1; +1; , , x *. , , . , , .

+3

, :

echo "|| x ||| + ||" | tr -d ' ' | \
awk -F "+" '{out="("$1; for(i=2;i<=NF;i++){out=out")+("$i}; print out")"}' | \
awk -F "x" '{out="("$1; for(i=2;i<=NF;i++){out=out")*("$i}; print out")"}'| \
sed 's/|/1+/g' | \
sed 's/+)/)/g' | \
bc

awk parens; , -F.

+2

, | - :

# Assign string to $1
set -- '|| x ||| + ||'

result=$(echo "$1" | 
  awk '{ 
        for(i=1; i<=NF; ++i) {
          if ($i ~ /^\|+$/) { $i = length($i) }
          else if ($i == "x") { $i = "*" }
        }
        print
      }' | bc)
  • (awk): 2 * 3 + 2, bc ( OP miken32, 6 5 ).
    • for(i=1; i<=NF; ++i) , , .
    • if ($i ~ /^\|+$/) { $i = length($i) } |. , , .
    • else if ($i == "x") { $i = "*" } x *, bc * .
    • Assigning input fields ( $i), the input line will be restored with the new values, and printjust print the resulting line.
+2
source

EDITED follows the sentence in a comment (by mklement0).

Here's how I do it:

#!/bin/bash

read -ra flds <<< '|| x ||| + ||'

# for each substring in string
for c in "${flds[@]}"
    do
        # compute string length
        len=${#c}
        # if the first char in c is a | then the corresponding length is the number, append it to a string
        if [[ "${c:0:1}" == "|" ]]; then str=$str"$len"
        # check for + and * and append them to the string
        elif [ "${c:0:1}" == "+" ]; then str=$str"+"
        elif [ "${c:0:1}" == "x" ]; then str=$str"*" 
        fi
    done
#evaluate the string via bc
echo "$str"|bc
+2
source

Source: https://habr.com/ru/post/1616642/


All Articles