Я являюсь новым со сценариями, и я хочу записать сценарий, который должен обработать, это - аргумент (аргументы) как следующее:
$ tandenstokers "| | x|| | |+|"
|| x |||| + | = 9 (11 tandenstokers)
$ tandenstokers \| \| x\|\| \| \|\+\|
|| x |||| + | = 9 (11 tandenstokers)
Где, поскольку я получаю это, как произведено:
$ tandenstokers \| \| x\|\| \| \|\+\|
|| x |||| + | = 0 (0 tandenstokers)
То, что это делает, в основном считать сумму 'палок' и применить простую математику к нему. Получающийся вывод: 1. Данный аргумент (аргументы) с только располагает с интервалами оставленный прежде и после x или + 2. 9 в примере выше результат математики. 3. 11 сумма палок, используемых в формуле (+ и количество x как две палки)
До сих пор у меня есть следующий код, и я не понимаю, где моя ошибка:
#!/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)"
В первую очередь, для ответа на вопрос, -eq
для целочисленного сравнения. Использовать =
для строк. Я предполагаю, что это - Ваша основная ошибка.
Некоторый совет:
"$n"
, не просто $n
). Закрытие кавычки их может быть необходимым в некотором случае, но это должно быть исключениеset -u
обнаружить использование неинициализированных переменныхsed -e 's/ //g; s/[+x]/ & /g;'
вместо трех конвейеров команд sed -e 's/ //g' | sed -e 's/+/ + /g' | sed -e 's/x/ x /g'
for word in "$@"
). Здесь, то, что я вижу, является большим циклом с большим количеством из N++
и Вы анализируете все сами, символ символом.Для забавы гольфа кода вот часть вычисления в одном sed + арифметическая оценка:
tandenstokers()
{
echo "$((
$(sed -e '
s/ //g
s/[xX]/*/g
s/|\+/\(&\)/g
s/|/+1/g
' <<< "$*" )
))"
}
$ tandenstokers "| | x|| | |+|"
9
$ tandenstokers "|| + ||| - | X |||| / ||"
3
Это - радикально другое решение. Возьмите его в качестве любопытства и не отбрасывайте Ваш! То, что я делаю, просто поворачивает Вашу 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)"
Я боюсь, что Ваш сценарий не очень легко понять. Ваш подход кажется чрезмерно сложным для того, что он пытается сделать и так как Вы не объясняете, что Вы думаете, что каждая часть Вашего сценария делает, это не тривиально для понимания этого.
Тем не менее Ваш первый выпуск (то, которое было бы очевидно, имело Вас, включал сообщения об ошибках), то, что Вы используете -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
символы долго.
Первое правило к программированию на любом языке: когда что-то пойдет не так, как надо, распечатайте все переменные. 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)