Баш не может заставить ЕСЛИ работать так, как я хочу - PullRequest
0 голосов
/ 12 октября 2009

Мне нужно понять выражения bash if. Конечно, я использовал Google. Я знаю, что это выглядит примерно так:

if [ expr operator expr ]
then
doSomeThing
fi

Однако я понимаю, что Bash не имеет логического типа данных. Я хочу проверить, существует ли файл, переданный в качестве аргумента ($ 1). То, как я поступил бы так:

if [ -e $1 = true ] 
then 
echo "File exists."
fḯ

Или, может быть, как:

if [ -e $1 ] #Assuming that this is true only if file in $1 exists. 

Ничего из этого не работает, и я не уверен, что [] означает. -e $ 1 кажется разумным выбором, но всегда ли это правда? Существуют разные операторы для строк и целых чисел. И я не могу использовать скобки для группировки выражений. Это так запутанно.

Кто-нибудь получил несколько подсказок? IF в bash не работает, как если бы я пробовал на любом другом языке.

Ответы [ 4 ]

3 голосов
/ 13 октября 2009

Как уже упоминалось, [ на самом деле является командой test, поэтому ее аргументы анализируются в соответствии со стандартным правилом разбора аргументов, и это вызывает некоторый довольно неудобный и запутанный синтаксис. Например, вы можете использовать скобки, < и > в тестовых командах, но вам лучше избегать их, иначе оболочка примет их как нечто неудачное.

Существует гораздо лучшее решение: условное выражение , которое во многом похоже на команду теста старой школы, но с [[ ]] вместо [ ] вокруг выражения. Поскольку это не анализируется как команда, он имеет гораздо более естественный синтаксис, а также обладает некоторыми более мощными функциями:

if [[ -e $1 && ! -d $1 ]]; then  # if $1 exists but isn't a directory...
    # note that quotes are not needed, since $1 will not undergo word splitting
[[ $string == done ]] # string comparison
[[ $string == a* ]] # glob-style pattern matching: does $string start with "a"?
[[ $string == "*"* ]] # partial glob: does $string start with "*"?
[[ $string =~ ^[[:upper:]] ]] # regex matching: does $string start with an upper-case letter?
[[ $string < g ]] # string comparison: is $string alphabetically before "g"
[[ $num -lt 5 ]] # numeric comparison: is $num numerically less than 5
3 голосов
/ 12 октября 2009

[...]

означает, что программа /usr/bin/test выполняется с ... в качестве аргументов и проверяется ее возвращаемое значение (0 означает true, а x != 0 означает false (да, 0 действительно означает true здесь, потому что 0 - это код выхода OK в UNIX)). Так

if [ -e $1 ]; then
    echo "ok"
fi

правильно. Это так же, как

if test -e $1; then
    echo "ok"
fi

Единственная проблема в том, что $1 может содержать пробелы. Если так, то /usr/bin/test запутывается, так как получает 3 или более аргументов. Первый (-e) - унарный оператор (требуется один аргумент). Так как вы дали ему 2 или более (один /usr/bin/test аргумент - сам -e), он жалуется так:

...: binary operator expected

Итак, просто используйте

if [ -e "$1" ];then
    echo "ok"
fi

Это будет работать, даже если $1 содержит пробелы. Другая возможность заключается в использовании

if [[ -e $1 ]]; then
    echo "ok"
fi

Это будет делать то же самое, но оно оценивается самим bash, и /usr/bin/test программа не получает разветвления.

Соединения, как обычно, но -a означает and, а -o означает or. Так

if [ -e /etc/fstab -a -e "$1" ]; then
   echo "ok"
fi

будет отображаться нормально, если /etc/fstab и файл, указанный в качестве первого аргумента командной строки, существует.

0 голосов
/ 12 октября 2009
  1. см. man test
  2. это должно работать:

    function foo() {
      if [ -e "$1" ] ; then
        echo "$1 exists"
      fi
    }
    
  3. Существует несколько способов написания составных выражений: и:

    [ expr1 -a expr2 ]
    

    или

    [ expr1 -o expr2 ]
    

    Вы также можете использовать синтаксис [[ expr && expr || expr ]]

0 голосов
/ 12 октября 2009

[] является сокращением для команды bash test http://ss64.com/bash/test.html

если операция в bash проверяет, равен ли код возврата команды, используемой для тестирования, 0.

Вы можете проверить статус возврата любой команды с помощью: echo $?

Например попробуйте это:

test -e myfile.txt
echo $?
[ -e myfile.txt ] 
echo ?$
...