Вопрос или проблема
У меня есть файл с именем ‘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
-
$file должен показывать содержимое переменной file, так что должен выводиться
ps -aux|head -n 5
но почему выводится результат выполнения ps -aux|head -n 5, а не просто показывается ps -aux|head -n 5? -
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
и подставляет ее вывод в код скрипта.
Пример
Теперь, основываясь на предоставленном вами примере:
-
Путь
/home/somepath/fileWithOneCommand.txt
: Этот файл содержит командуps -aux|head -n 5
. -
Скрипт
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.