скрипт bash с использованием простых математических заметок

Я новичок в написании сценариев, и я хочу написать скрипт, который должен обрабатывать его аргументы следующим образом:

$ tandenstokers "| | x|| | |+|"
|| x |||| + | = 9 (11 tandenstokers)

$ tandenstokers \| \| x\|\| \| \|\+\|
|| x |||| + | = 9 (11 tandenstokers)

Где, как я получаю это как вывод:

[ f2]

То, что он делает, в основном подсчитывает количество «палочек» и применяет к нему простые математические данные. Результирующий результат: 1. Данный аргумент (ы) с пробелами, оставленными до и после x или + 2. 9 в приведенном выше примере, является результатом математики. 3. 11 - количество палочек, используемых в формуле (a + и ax, как две палочки)

До сих пор у меня есть следующий код, и я не понимаю, где моя ошибка:

#!/bin/bash

uitdrukking="$*"
size=${#uitdrukking}
mooi=$(echo "$uitdrukking" | sed -e 's/ //g' | sed -e 's/+/ + /g' | sed -e 's/x/ x /g')
x=0
y=1
a=1
n=0
m=0
sub=0
while [ $a -le $size ]
do
((a++))
    if [ ${uitdrukking:$x:$y} -eq "|" ]
        then
            ((n++))
            ((x++))
            ((y++))
            ((m++))
    elif [ ${uitdrukking:$x:$y} -eq "+" ]
        then
            ((x++))
            ((y++))
            m=$[ $m + 2 ]
    elif [ ${uitdrukking:$x:$y} -eq "x" ]
        then
        ((x++))
        ((y++))
        m=$[ $m + 2 ]
            while [ ${uitdrukking:$x:$y} -eq "|" ]
            do
                ((sub++))
                ((x++))
                ((y++))
                ((m++))
            done
            n=$[ $n * $sub ]
    else
        ((x++))
        ((y++))
    fi
    done
echo "$mooi = $n ($m tandenstokers)"

Решил эту проблему, начиная с нуля с помощью другого подхода, в результате чего появился следующий правильный код:

#!/bin/bash
echo "$(echo "$*" | sed -e 's/ //g' | sed -e 's/+/ + /g' | sed -e 's/x/ x /g') = $(($(echo "$*" | sed -e 's/ //g' | sed -e 's/\(\|[^x+]*\)/(\1)/g' | sed -e 's/|/1 + /g' | sed -e 's/ + $//g' | sed -e 's/ + +/ + /g' | sed -e 's/ + x/ \* /g' | sed -e 's/ + \([^1]\)/\1/g' | sed -e 's/x/ \* /g'))) ($(($(echo "$*" | sed -e 's/ //g' | sed -e 's/|/1 p /g' | sed -e 's/ p $//g' | sed -e 's/x/2 p /g' | sed -e 's/+/2 p /g' | sed -e 's/p/+/g'))) tandenstokers)"
1
задан 7 December 2016 в 21:32

2 ответа

Боюсь, ваш сценарий не так-то просто понять. Ваш подход кажется чрезмерно сложным для того, что он пытается сделать, и поскольку вы не объясняете, что, по вашему мнению, каждая часть вашего скрипта, нетрудно понять это.

Тем не менее, ваша первая проблема (которая была бы очевидна, если бы вы включили сообщения об ошибках) заключается в том, что вы используете -eq для лексического сравнения. Вам нужно =, так как вы соответствуете строкам, а не цифрам.

Следующая проблема, которая снова будет очевидна из сообщений об ошибках, это

/home/terdon/scripts/foo.sh: line 15: [: too many arguments
/home/terdon/scripts/foo.sh: line 21: [: too many arguments
/home/terdon/scripts/foo.sh: line 26: [: too many arguments

Это связано с тем, что различные ${uitdrukking:$x:$y} расширяются до строк, содержащих пробелы, а не для одного символа , Вероятно, это связано с тем, что вы увеличиваете количество различных переменных счетчика во многих местах, поэтому ваш $y будет >1 очень быстро. Я думаю (но, опять же, я могу «быть уверенным, потому что ваш вопрос на самом деле не объясняет, что вы думаете»), что вы неправильно поняли, как работает синтаксис ${var:x:y}. Он не извлекает подстроку var из положения x в положение y. Он извлекает подстроку var, начиная с позиций x и y символов.

Первое правило программирования в символах long - это: когда что-то пойдет не так, распечатайте все переменные. 9 раз из 10, проблема в том, что переменная не имеет того значения, которое, по вашему мнению, имеет.

В любом случае у вас слишком много проблем для отладки здесь, и это было бы намного проще потребовать с нуля. Например, этот скрипт делает то, что вы хотите:

#!/bin/bash
mooi=$(echo "$*" | sed -e 's/ //g' | sed -e 's/+/ + /g' | sed -e 's/x/ x /g')
## I use fold to print one character at a time and then iterate
## over the resulting strings. 
while read char; do
    case $char in
        ## If this is a |, increment the total number of |
        ## found and the current number (until the next operator).
        "|")
            ((pipeNum++))
            ((totPipes++))
            ;;
        ## If this is an operator
        [+x])
            ## Change x to * for bc
            char=$(echo "$char" | tr 'x' '*')
            ## Increment the operator count by 2 as requested. 
            operators=$((operators + 2))
            ## Append the number of pipes so far and the 
            ## current operator to the $string variable. This 
            ## will hold the expression we'll give to bc. 
            string="$string $pipeNum $char"
            ## reset the pipeNum to 0 for the next operation. 
            pipeNum=0
            ;;
            ## Ignore all other cases. 
            "*")
                continue
                ;;
    esac
done < <(fold -w 1 <<<"$*")
## Add the last set. 
string="$string $pipeNum"
## Count the total
tandenstokers=$((totPipes + operators))
## Use bc to calculate
echo "$mooi = $(echo "$string" | bc) ($tandenstokers tandenstokers)"

Чтобы увидеть его в действии:

$ foo.sh '| | x | | | | + |'
|| x |||| + | = 9 (11 tandenstokers)
$ foo.sh \| \| x\|\| \| \|\+\|
|| x |||| + | = 9 (11 tandenstokers)
4
ответ дан 23 May 2018 в 03:34
  • 1
    Спасибо за вашу помощь, я заметил это в коде: & lt; & lt; (fold -w 1 & lt; & lt; " $ * "), что именно это делает? – noone 7 December 2016 в 21:28
  • 2
    @ noone fold команда " складывает " его вход. В этом случае из-за -w 1 он печатает по одному символу в строке. Если вы использовали w -12, он будет печатать по 12 на линию и так далее. – terdon♦ 7 December 2016 в 21:37

Это мое рабочее решение для проблемы:

#!/bin/bash
echo "$(echo "$*" | sed -e 's/ //g' | sed -e 's/+/ + /g' | sed -e 's/x/ x /g') = $(($(echo "$*" | sed -e 's/ //g' | sed -e 's/\(\|[^x+]*\)/(\1)/g' | sed -e 's/|/1 + /g' | sed -e 's/ + $//g' | sed -e 's/ + +/ + /g' | sed -e 's/ + x/ \* /g' | sed -e 's/ + \([^1]\)/\1/g' | sed -e 's/x/ \* /g'))) ($(($(echo "$*" | sed -e 's/ //g' | sed -e 's/|/1 p /g' | sed -e 's/ p $//g' | sed -e 's/x/2 p /g' | sed -e 's/+/2 p /g' | sed -e 's/p/+/g'))) tandenstokers)"
0
ответ дан 23 May 2018 в 03:34

Другие вопросы по тегам:

Похожие вопросы: