Мой сценарий:

#!/bin/bash

generic()
{

    echo $1;
    $1 > temp.txt 2>&1
}

generic "echo asd > /dev/null 2>&1; echo temp"

Ожидаемый результат:

  1. "asd" должен идти в / dev / null
  2. "temp" должен войти в файл temp.txt.

Фактический результат:

  1. "asd> / dev / null 2> & 1; echo temp" переходит в файл temp.txt.

Почему запускается только первый оператор echo, а его вывод перенаправляется на temp.txt. Кроме того, почему вторая команда обрабатывается как строка?

0
Naveen 29 Сен 2013 в 14:51

1 ответ

Лучший ответ

Вам необходимо прочитать spec.

(Это спецификация POSIX sh, потому что у bash нет настоящей спецификации. Bash пытается быть совместимым с POSIX sh, но добавляет кучу ненужных сложностей. Вместо этого вы должны использовать #!/bin/sh как новичок и всякий раз, когда вы хотите напишите вменяемый сценарий)

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

Разбиение происходит по пробелу или чему-то еще внутри переменной IFS. В вашем примере это приведет к следующему списку токенов:

  1. эхо
  2. ASD
  3. >
  4. / dev / null
  5. 2> & 1;
  6. эхо
  7. темп

Этот список затем выполняется как процесс, эквивалентный записи в C execlp("echo", "echo", "asd", ">", "/dev/null", "2>&1;", "echo", "temp", NULL);.

Обратите внимание, что если бы вы вместо этого написали "$1", это привело бы к тому, что оболочка попыталась запустить программу с именем echo asd > /dev/null 2>&1; echo temp без аргументов.

Если вместо этого вы хотите переоценить строку как командную строку оболочки, вам нужно использовать eval: eval "$1". Но помните о последствиях для безопасности! Многие считают Эвал злом.

0
Jo So 29 Сен 2013 в 15:14