Подстановка команд и знак доллара перед переменной

Вопрос или проблема

У меня есть файл с именем ‘fileWithOneCommand.txt’ с одной командой, как показано ниже:

ps -aux|head -n 5

затем я пишу тестовый скрипт shell с именем ‘test5.sh’ со следующим содержимым:

file=/home/somepath/fileWithOneCommand.txt
$file;
echo see;
cat $file;
echo see2;
$(cat $file);
echo see3;

но я не могу понять результат, результат следующий:

$ ./test5.sh
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 168584 10308 ?        Ss   Feb19   0:49 /sbin/init splash
root           2  0.0  0.0      0     0 ?        S    Feb19   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        S    Feb19   0:00 [pool_workqueue_release]
root           4  0.0  0.0      0     0 ?        I<   Feb19   0:00 [kworker/R-rcu_g]
see
ps -aux|head -n 5
see2
error: user name does not exist

Usage:
 ps [options]

 Try 'ps --help <simple|list|output|threads|misc|all>'
  or 'ps --help <s|l|o|t|m|a>'
 for additional help text.

For more details see ps(1).
see3
  1. $file должен показывать содержимое переменной file, так что должен выводиться
    ps -aux|head -n 5
    но почему выводится результат выполнения ps -aux|head -n 5, а не просто показывается ps -aux|head -n 5?

  2. cat $file; возвращает ps -aux|head -n 5, но почему

$(cat $file);

возвращает ошибку “error: user name does not exist”?

Как я нагуглил команду подстановки, там сказано, что “вывод команды заменяет саму команду. Shell выполняет расширение, выполняя команду, а затем заменяя подстановку команды стандартным выводом команды.”

так что для

$(cat $file);

внутри скобок cat $file возвращает ps -aux|head -n 5
так почему $(cat $file);
не возвращает результат выполнения ps -aux|head -n 5, а возвращает ошибку “error: user name does not exist”?

Ответ или решение

Командная подстановка и использование знака доллара перед переменной — это две концепции в оболочках Unix, которые могут вводить в заблуждение, если не иметь достаточного опыта работы с ними. Разберем эти вопросы подробно, используя ваш пример для объяснения.

Теория

1. Знак доллара перед переменной

Знак доллара ($) в скриптах bash используется для обращения к значению переменной. Когда вы пишете $file, оболочка bash подставляет значение переменной file в этой позиции. Таким образом, вместо обращения непосредственно к переменной, вы фактически получаете строку, содержащую путь /home/somepath/fileWithOneCommand.txt.

2. Командная подстановка

Командная подстановка используется для выполнения команды и получения ее вывода как результата. В bash это реализуется при помощи обратных кавычек (`) или конструкции $(). Например, $(ps -aux | head -n 5) выполняет команду ps -aux | head -n 5 и подставляет ее вывод в код скрипта.

Пример

Теперь, основываясь на предоставленном вами примере:

  1. Путь /home/somepath/fileWithOneCommand.txt: Этот файл содержит команду ps -aux|head -n 5.

  2. Скрипт test5.sh:

    file=/home/somepath/fileWithOneCommand.txt
    $file;
    echo see;
    cat $file;
    echo see2;
    $(cat $file);
    echo see3;

Скрипт выполняет следующие действия:

  • Строка $file;: Тут происходит выполнение содержимого файла fileWithOneCommand.txt как команды. Оболочка bash сначала заменяет $file на /home/somepath/fileWithOneCommand.txt, а затем выполняет содержащуюся в файле команду ps -aux|head -n 5. Поэтому вы видите вывод команды ps.

  • Строка echo see; просто выводит see на экран.

  • Строка cat $file;: Здесь выполнение команды cat отображает содержимое файла fileWithOneCommand.txt, которое равно ps -aux|head -n 5.

  • Строка echo see2; аналогично предыдущей, выводит see2.

  • Строка $(cat $file);: Эта строка вызывает командную подстановку. cat $file возвращает ps -aux|head -n 5, что фактически выполняет команду ps -aux|head -n 5;. Ошибка возникает, потому что синтаксис команд ps отличается и требует дополнительных параметров в вашей системе. Ошибка, которую вы видите — это результат некорректного выполнения этой команды в контексте вашей системы.

Применение

Чтобы избежать путаницы и неожиданных ошибок при использовании этих конструкций, рекомендуется следовать ряду практик:

  • Явное объявление команд: Если вы хотите выполнить команду из файла, используйте что-то вроде bash $(cat $file), чтобы явно указать, что это команда, требующая выполнения.

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

  • Использование отладочных техник: Перед выполнением скрипта используйте echo для проверки значений, которые будут подставлены вместо переменных, чтобы исключить ошибки синтаксиса или недостатки содержания файла.

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

Оцените материал
Добавить комментарий

Капча загружается...