Я знаю, что переменные в bash не имеют типа, но я не совсем понимаю, какое значение им присвоено.
Следующий простой скрипт отлично работает в bash
#!/bin/bash
tail -n +2 /cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile.txt > \
/cygdrive/c/workdir\ \(newco\,\ LLC\)/workfile2.txt
Тем не менее, следующее не
#!/bin/bash
tmpdir=/cygdrive/c/workdir\ \(newco\,\ LLC\)
tail -n +2 $tmpdir/workfile.txt > $tmpdir/workfile2.txt
Есть ли объяснение этому поведению?
tmp
вы можете сделать что-то вроде${tmp}dir/workfile.txt
замены вместо целой$tmpdir
(при условии, что она тоже существует).Введите первую строку в bash, а затем отобразите эту переменную, вот что вы увидите:
Если еще не ясно, кто виноват, добавьте
echo
в начале второй строки и заключите в двойные кавычки. Вы увидите, какая команда на самом деле выполняется:Вы правильно избежали назначения переменных, но этого недостаточно. Bash выполняет простую подстановку подстрок, вставляя дополнительные пробелы и нарушая вашу команду.
Как @savanto предложил в своем ответе, вы можете заключить переменные в двойные кавычки, чтобы лишние пробелы не обрабатывались как разделители аргументов. Эта строка:
будет выглядеть так после подстановки переменной:
Это наиболее распространенный и предпочтительный способ решения этой проблемы. Если вы отчаянно хотите избежать двойных кавычек, вы можете попробовать двойное экранирование: сначала при присваивании, затем после подстановки.
Быстрое объяснение тройной обратной косой черты: обратная косая черта означает: «обрабатывать следующий символ как обычный символ, игнорировать любое специальное значение» (т.е. избегать его ). Первая обратная косая черта является escape-символом, поэтому вторая будет рассматриваться как обратная косая черта, а не как escape-символ. Таким образом, двойной обратный слеш производит один обратный слеш. Третий просто избегает следующего символа, такого как пробел или скобка. Например
a\\\ b
станетa\ b
.Теперь, если мы подставим переменные в вашу команду, она будет экранирована правильно:
источник