根据数学规则乘以bash脚本

时间:2015-11-19 23:00:50

标签: bash shell

所以我有一个练习,我需要计算一个特定的字符串。

例如字符串“|| x ||| + ||”。垂直线代表1.所以这个字符串的解决方案必须是8.所以我制作了这个脚本:

#!/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)

但是当我在字符串示例上执行此脚本时,我得到的解决方案是6。 然后我发现它是因为脚本执行这个:1 + 1 * 1 + 1 + 1 + 1 + 1。所以我需要一种方法在(1 + 1)*(1 + 1 + 1)+(1 + 1)之间进行括号,但我无法弄明白。

任何人都可以帮助我吗? 提前致谢!

5 个答案:

答案 0 :(得分:3)

如果你想坚持使用sed,那么最好是在完成其余工作之前加入parens

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

答案 1 :(得分: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脚本用相同的序列和一个右括号替换一个或多个管道符号的每个序列;然后它用(1替换一系列管道符号开头的管道;然后用+1替换每个剩余的管道;最后用x替换*。它只要求管道是连续的,它们之间没有空隙。在完成其余工作之前,只需删除所有空格即可删除该约束。

答案 2 :(得分:2)

这是适用于您的样本数据的一个:

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标志。

答案 3 :(得分: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 + 2bc然后根据需要进行评估(对比度)这是OP的解决方案尝试和miken32's solution,分别使用 6 5 中间命令)。
    • for(i=1; i<=NF; ++i)遍历输入行中所有以空格分隔的字段。
    • if ($i ~ /^\|+$/) { $i = length($i) }取代每次|个字符。它的长度,有效地用它代表的数字代替它。
    • else if ($i == "x") { $i = "*" }x替换为*,因为bc期望*为乘法符号。
    • 通过分配输入字段($i),使用新值重建输入行,print只打印生成的行。

答案 4 :(得分:2)

已编辑以遵循评论中的建议(通过mklement0)。

我将如何做到这一点:

$('#sorting li').click(function(){
    $(this).addClass('current').siblings().removeClass('current');
});