2016-06-09 3 views
1

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

1 + 3 = 4, - и / также работает, но если я печатаю количество 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" 

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

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

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

+1

Когда вы запускаете 'count 1 * 3',' * 'заменяется списком имен файлов ** перед вызовом' count' **. Это означает, что 'count' не может ничего сделать, чтобы предотвратить это; замена произошла до того, как она была загружена или даже идентифицирована на диске. –

+0

Хорошо, спасибо, поэтому я должен переписать сценарий по-другому ... – Josh

+0

@Josh Мой ответ включает другой способ. – fuzz

ответ

0

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

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

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

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

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

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

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

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

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

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

Короче, цитирует все, где не требуется оболочка для выполнения маркеров расщепления и подстановочного расширения.

+0

Спасибо за ваше время. Да, я знаю, что если я напишу 2 '*' 1 или 2/* 1, это сработает, но мне было любопытно, есть ли способ просто набрать 2 * 2 без использования escape-символов в командной строке. – Josh

2

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

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

Некоторые опции:

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

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

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

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

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

    Это то, что expr.

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

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

+0

Я никогда раньше не видел этого волшебного алиаса; это красиво ужасно! –