Я написал этот скрипт:
#!/bin/bash
while [ true ]
do
currentoutput="$(lsusb)"
if [ "$currentoutput" != "$lastoutput" ]
then
echo "" date and Time >> test.log
date +%x_r >> test.log
lastoutput="$(lsusb)"
lsusb >> test.log
fi
sleep 5
done
Я новичок, пытающийся быстро учиться, и у меня возник вопрос о кавычках переменной .
Поместите переменную между $ (), я понял, но почему кавычки нужны даже в if
выражении? Это сделать вложенную команду?
while [ true ]
это создает бесконечный цикл, но, возможно, не по той причине, о которой вы думаете;while [ false ]
также создает бесконечный цикл, потому что с одним аргументом[ ... ]
успешно, если этот аргумент является непустой строкой.while true
фактически запустит команду с именемtrue
(которая всегда будет успешной).$()
. Вы вводите команду внутри$()
.Ответы:
Кавычки предотвращают «расщепление слов». Это значит: разбивать переменные на несколько элементов по пробельным символам (или, точнее, по пробелам, табуляциям и символам новой строки, как определено в значении
$IFS
переменной оболочки по умолчанию ).Например,
Здесь мы определяем
howmany
функцию, которая просто позволяет нам узнать, сколько задано позиционных параметров. Как видите, в переменную передаются два элемента, а с кавычками текст в переменной рассматривается как одна единица.Это важно для точной передачи информации. Например, если переменная содержит путь к файлу, а имя файла содержит пробелы в любом месте пути, команда, которую вы пытаетесь выполнить, может дать сбой или дать неточные результаты. Если бы мы пытались создать файл с
$var
переменной,touch $var
то создали бы два файла, ноtouch "$var"
только один.То же самое относится и к вашей
[ "$currentoutput" != "$lastoutput" ]
части. Этот конкретный тест выполняет сравнение двух строк. Когда тест выполняется,[
команда должна увидеть 3 аргумента - текстовую строку,!=
оператор и другую текстовую строку. Хранение двойных кавычек предотвращает разбиение слов, и[
команда видит именно эти 3 аргумента. Что будет, если переменные не заключены в кавычки?Здесь слово расщепление происходит, и вместо этого
[
видит две строкиhello
иworld
затем!=
, за которыми следуют две другие строкиhi world
. Ключевым моментом является то, что без двойных кавычек содержимое переменных понимается как отдельные единицы, а не как единое целое.Назначение подстановки команд не требует двойных кавычек, как в
где вы сохранили
df
вывод командыvar
. Тем не менее, это хорошая привычка всегда заключать в кавычки переменные и подстановку команд,$(...)
если вы на самом деле не хотите, чтобы вывод обрабатывался как отдельные элементы.На заметку,
часть может быть
[
это команда, которая оценивает свои аргументы и[ whatever ]
всегда верна независимо от того, что находится внутри. Напротив,while true
использует команду,true
которая всегда возвращает статус успешного завершения (и это именно то, чтоwhile
нужно циклу). Разница в большей ясности и меньшем количестве выполненных тестов. В качестве альтернативы, вы также можете использовать:
вместоtrue
Двойные кавычки
echo "" date and Time
частично могут быть удалены. Они просто вставляют пустую строку и добавляют дополнительное пространство к выводу. Если это желательно, не стесняйтесь держать их там, но в этом случае нет особой функциональной ценности.Эта часть, вероятно, может быть заменена на
echo "$currentoutput" >> test.log
. Нет причинlsusb
снова запускаться после того, как он уже был запущенcurrentoutput=$(lsusb)
. В тех случаях, когда конечные символы новой строки должны быть сохранены в выходных данных - можно увидеть значение при запуске команды несколько раз, но вlsusb
этом нет необходимости. Чем меньше внешних команд вы вызываете, тем лучше, потому что каждый вызов не встроенной команды влечет за собой затраты на ЦП, использование памяти и время выполнения (даже если команды, вероятно, предварительно загружены из памяти).Смотрите также:
источник
bash
. Но в последней части не должно бытьecho "$currentoutput" >> test.log
лучшеprintf '%s\n' "$currentoutput" >> test.log
?printf
должно быть предпочтительным для мобильности. Так как мы используем специфичный для bash скрипт, его можно оправдатьecho
. Но ваши наблюдения очень верныecho
это вполне надежны , даже если оболочка , как известно Баш (и значениеxpg_echo
иposix
флагов известно); если ваше значение может быть-n
или-e
, оно может исчезнуть вместо печати.В
currentoutput="$(lsusb)"
lsusb это не переменная, это команда. Что делает этот оператор, он выполняетlsusb
команду и назначает свой выводcurrentoutput
переменной.Более старый синтаксис для этого был
Вы можете найти это во многих примерах и сценариях
Чтобы ответить на другую часть вашего вопроса,
if [ ]
просто как синтаксис дляif
определяется в bash. Подробнее см. В https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html.источник
[ ]
это на самом делеtest
команда. Вы также можете использоватьif
операторы с другими командами, так как они основаны на 0 или ненулевом тесте их кода выхода.if grep -qe "somestring" file
чем запускатьgrep -qe "somestring" file; if [ $? = 0 ]; then ...
, поэтому утверждение,if [ ...
являющееся частью определенияif
синтаксиса, не просто вводит в заблуждение, но ведет к неправильным действиям.Следующая команда запускает внешнюю команду
command
и возвращает ее вывод.Без скобок / скобок, это будет искать переменную вместо выполнения команды:
Что касается разницы между
$variable
и"$variable"
, это становится актуальным, когда$variable
содержит пробелы. При использовании"$variable"
все содержимое переменной будет вставлено в одну строку, даже если содержимое содержит пробелы. При использовании$variable
содержимое переменной может быть расширено в список аргументов из нескольких аргументов.источник
Для противоположности - bash рекомендует использовать конструкцию
[[ ... ]]
over,[ ... ]
чтобы избежать кавычек переменных в тесте и связанных с этим проблем разделения слов, на которые указывали другие.[
предоставляется в bash для совместимости POSIX со сценариями, предназначенными для запуска,#!/bin/sh
или со сценариями , переносимыми в bash - по большей части вы должны избегать его в пользу[[
.например
источник
bash
не дает такой рекомендации; он предоставляет[[ ... ]]
более удобный способ и имеет некоторые функциональные возможности, которых[ ... ]
нет, но нет проблем с[ ... ]
правильным использованием .[[
делает все[
, и даже больше, и все же много раз[
сбивает людей с толку, а затем пытается и модернизировать функции[[
обратно, чтобы[
только потерпеть неудачу и оставить ошибки рассеянными - справедливо сказать, что это Рекомендация сообщества в том, что касается наиболее важных руководств по bash, никогда не используйте[
.