Как отключить специальные символы в bash?

Я создал скрипт, который выполняет расчет. Например:count 1 + 3

1 + 3 = 4,- а также / тоже работает, но если я наберу count 1 * 3, Я получил

Должен быть номер операнда номер

Вот часть сценария:

if [ "$#" -ne 3 ]; then
        echo "Should be number operand number"
        exit 1
fi
...
elif [ "$2" = "*" ]; then
        result=`echo $1 \* $3 | bc`
  echo "$1 * $3 = $result"

Да, если я наберу \ до * в командной строке это будет работать, но мне нужно, чтобы он работал только с *,

Я пытался использовать набор -f внутри скрипта он не работал (да, он отключает специальные символы, если я набираю сам bash, но это не то, что мне нужно). Также есть shopt команда, которая контролирует поведение оболочки, поэтому я попытался включить некоторые параметры, такие как shopt -s globstar, nullglob, promptvarsи т.д. Это не сработало. Я поставил команду перед оператором if, может быть, это неправильно.

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

2 ответа

Эта точная проблема упоминается в спецификации POSIX выражения expr, где говорится, что инструмент имеет "довольно сложный синтаксис" по той причине, которую вы описываете.

Другими словами, это определенно известная проблема, и сам POSIX оставляет ее нерешенной. Вы действительно должны подумать о работе с Unix и делать то же самое, а не пытаться работать против него.

Некоторые варианты:

  • Требовать полного выражения для одного аргумента в кавычках, например count "1 * 2"

    Это прагматичный, безотказный способ гарантировать, что аргумент всегда заключается в кавычки, так что любое введение * все еще работает. Встроенный bash let Является ли это.

  • read выражение себя, например, просто запустить count а затем введите 1 * 2,

    Это позволяет избежать того, что оболочка касается ваших данных, поэтому вы можете интерпретировать их так, как хотите. Это что bc а также dc делать.

  • Жить с тем, что мимоходом * потребует тщательного цитирования.

    Это то, что expr делает.

  • Используйте магический псевдоним, который работает только на определенных оболочках при определенных обстоятельствах.

    Это то, что никто не делает, потому что оно хрупкое и непредсказуемое, хотя в некоторых случаях позволяет использовать нужный синтаксис.

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

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR

Если вы не используете двойные кавычки, bash увидит * и выполнить расширение имени файла. * расширяется на все файлы в вашем текущем каталоге.

Однако, говоря это, вы должны использовать одинарные кавычки для *:

#!/bin/bash
if [ "$2" = "*" ]; then
    result=`echo $1 \* $3 | bc`
    echo "$1 * $3 = $result"
fi

Следующее будет работать:

» count.sh 2 '*' 1
2 * 2 = 4

Вы ничего не можете сделать в своей программе, потому что * расширение выполняется оболочкой (в отличие от Windows, где это делается программой).

Вот еще один пример кода, использующий подход, основанный на меню:

#!/bin/bash
while true; do
    read -p "what's the first number? " n1
    read -p "what's the second number? " n2
    PS3="what's the operation? "
    select ans in add subtract multiply divide; do
        case $ans in 
            add) op='+' ; break ;;
            subtract) op='-' ; break ;;
            multiply) op='*' ; break ;;
            divide) op='/' ; break ;;
            *) echo "invalid response" ;;
        esac
    done
    ans=$(echo "$n1 $op $n2" | bc -l)
    printf "%s %s %s = %s\n\n" "$n1" "$op" "$n2" "$ans"
done

what's the first number? 5
what's the second number? 4
1) add
2) subtract
3) multiply
4) divide
what's the operation? /
invalid response
what's the operation? 4
5 / 4 = 1.25000000000000000000

Вкратце, процитируйте все, где вам не требуется оболочка для разделения токенов и подстановочных знаков.

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