Я написал этот сценарий:
#!/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
? Это сделать вложенную команду?
В currentoutput="$(lsusb)"
lsusb не является переменной, это команда. Что делает этот оператор, он выполняет команду lsusb
и присваивает свой вывод переменной currentoutput
.
Более старый синтаксис для этого был
currentoutput=`lsusb`
, вы можете найти его во многих примерах и сценариях
Чтобы ответить на другую часть вашего вопроса, if [ ]
- это просто синтаксис 115] определяется в bash. Подробнее см. В https://www.tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html
Следующая команда запускает внешнюю команду command
и возвращает ее вывод.
"$(command)"
Без скобок / круглых скобок это будет искать переменную вместо выполнения команды:
"$variable"
Что касается разницы между $variable
и "$variable"
, это становится актуальным, когда $variable
содержит пробелы. При использовании "$variable"
все содержимое переменной будет вставлено в одну строку, даже если содержимое содержит пробелы. При использовании $variable
содержимое переменной может быть расширено до списка аргументов из нескольких аргументов.
Для противоположности - bash рекомендует использовать [[ ... ]]
над конструкцией [ ... ]
, чтобы избежать необходимости заключать в кавычки переменные в тесте и, следовательно, связанные с этим проблемы разбиения слов, на которые указывали другие.
[
предоставляется в bash для совместимости POSIX со сценариями, предназначенными для работы в #!/bin/sh
, или сценариями, переносимыми в bash - по большей части вам следует избегать его в пользу [[
. [ 117]
, например,
# With [ - quotes are needed
$ foo='one two'; bar='one two'; [ $foo = $bar ] && echo "they're equal"
-bash: [: too many arguments
$ foo='one two'; bar='one two'; [ "$foo" = "$bar" ] && echo "they're equal"
they're equal
# versus [[ - quotes not needed
$ foo='one two'; bar='one two'; [[ $foo = $bar ]] && echo "they're equal"
they're equal
Кавычки предотвращают "разделение слова". Это: ломая переменные в несколько объектов в пробельных символах (или быть более точным, в пробелах, вкладках и новых строках, как определено в значении значения по умолчанию $IFS
окружите переменную).
Например,
$ var="one two"
$ howmany(){ echo $#; }
$ howmany $var
2
$ howmany "$var"
1
Здесь мы определяем howmany
функция, которая просто сообщает нам, сколько позиционных параметров дано. Как Вы видите, существует два объекта, передаваемые переменной, и с кавычками текст в переменной рассматривают как одну единицу.
Это важно для точной передачи информации. Например, если переменная содержит путь к файлу, и имя файла содержит пробелы где угодно в пути, команда, которую Вы пытаетесь выполнить, может привести к сбою или дать неточные результаты. Если мы пытались создать файл с $var
переменная, touch $var
создал бы два файла, но touch "$var"
всего один.
То же идет для Вашего [ "$currentoutput" != "$lastoutput" ]
часть. Этот конкретный тест выполняет сравнение на двух строках. Когда тестовые прогоны, [
команда должна была бы видеть 3 аргумента - текстовая строка, !=
оператор и другая текстовая строка. Хранение двойных кавычек предотвращает разделение слова, и [
команда видит точно те 3 аргумента. Теперь, что происходит, если переменные закрываются кавычки?
$ var="hello world"
$ foo="hi world"
$ [ $var != $foo ]
bash: [: too many arguments
$
Здесь, разделение слова происходит, и вместо этого [
видит две строки hello
и world
сопровождаемый !=
, сопровождаемый двумя другими строками hi world
. Ключевой пункт - то, что без двойных кавычек, содержание переменных понято как отдельные единицы, а не один целый объект.
Присвоение замены команды не требует двойных кавычек как в
var=$( df )
где Вы имеете df
вывод команды, сохраненный к var
. Однако это - хорошая привычка к всегда переменным двойной кавычки и замене команды $(...)
если Вы действительно на самом деле не хотите, чтобы вывод рассматривался как отдельные объекты.
На ноте стороны,
while [ true ]
часть может быть
while true
[
команда, которая оценивает ее аргументы, и [ whatever ]
всегда верно независимо от того, что внутри. В отличие от этого, while true
использует команду true
который всегда возвращает статус выхода успеха (и это точно что while
потребности цикла). Различием является немного больше ясности и меньше выполненного тестирования. С другой стороны, Вы могли также использовать :
вместо true
Двойные кавычки в echo "" date and Time
часть могла, вероятно, быть удалена. Они просто вставляют пустую строку и добавить дополнительное пространство к выводу. Если это желаемо, не стесняйтесь сохранять их там, но в этом случае нет никакого конкретного функционального значения.
lsusb >> test.log
Эта часть могла, вероятно, быть заменена echo "$currentoutput" >> test.log
. Нет никакой причины работать lsusb
снова после того, как это уже было выполнено в currentoutput=$(lsusb)
. В случаях, где запаздывающие новые строки должны быть сохранены в выводе - каждый видел значение в выполнении команды многократно, но в случае lsusb
нет никакой потребности в этом. Чем менее внешние команды Вы называете, тем лучше, потому что каждый вызов к невстроенной команде несет расходы в ЦП, использовании памяти, и время выполнения (даже при том, что команды, вероятно, предварительно загружены из памяти).
См. также: